mirror of
https://github.com/postgres/postgres.git
synced 2025-08-25 20:23:07 +03:00
pgindent run.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.14 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.15 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
#include "postgres_fe.h"
|
||||
@@ -15,49 +15,48 @@
|
||||
#ifdef USE_THREADS
|
||||
static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
static struct connection *all_connections = NULL;
|
||||
static struct connection *all_connections = NULL;
|
||||
static struct connection *actual_connection = NULL;
|
||||
|
||||
static struct connection *
|
||||
ecpg_get_connection_nr(const char *connection_name)
|
||||
{
|
||||
struct connection *ret = NULL;
|
||||
struct connection *ret = NULL;
|
||||
|
||||
if( (connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0) )
|
||||
{
|
||||
ret = actual_connection;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct connection *con;
|
||||
|
||||
for( con = all_connections; con != NULL; con = con->next)
|
||||
if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
|
||||
ret = actual_connection;
|
||||
else
|
||||
{
|
||||
if( strcmp(connection_name, con->name) == 0 )
|
||||
break;
|
||||
}
|
||||
ret = con;
|
||||
}
|
||||
struct connection *con;
|
||||
|
||||
return( ret );
|
||||
for (con = all_connections; con != NULL; con = con->next)
|
||||
{
|
||||
if (strcmp(connection_name, con->name) == 0)
|
||||
break;
|
||||
}
|
||||
ret = con;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
struct connection *
|
||||
ECPGget_connection(const char *connection_name)
|
||||
{
|
||||
struct connection *ret = NULL;
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_lock(&connections_mutex);
|
||||
#endif
|
||||
|
||||
ret = ecpg_get_connection_nr(connection_name);
|
||||
struct connection *ret = NULL;
|
||||
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_unlock(&connections_mutex);
|
||||
pthread_mutex_lock(&connections_mutex);
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
|
||||
ret = ecpg_get_connection_nr(connection_name);
|
||||
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_unlock(&connections_mutex);
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -70,9 +69,10 @@ ecpg_finish(struct connection * act)
|
||||
|
||||
PQfinish(act->connection);
|
||||
|
||||
/* no need to lock connections_mutex - we're always called
|
||||
by ECPGdisconnect or ECPGconnect, which are holding
|
||||
the lock */
|
||||
/*
|
||||
* no need to lock connections_mutex - we're always called by
|
||||
* ECPGdisconnect or ECPGconnect, which are holding the lock
|
||||
*/
|
||||
|
||||
/* remove act from the list */
|
||||
if (act == all_connections)
|
||||
@@ -158,26 +158,26 @@ ECPGsetconn(int lineno, const char *connection_name)
|
||||
static void
|
||||
ECPGnoticeReceiver(void *arg, const PGresult *result)
|
||||
{
|
||||
char *sqlstate = PQresultErrorField(result, 'C');
|
||||
char *message = PQresultErrorField(result, 'M');
|
||||
char *sqlstate = PQresultErrorField(result, 'C');
|
||||
char *message = PQresultErrorField(result, 'M');
|
||||
struct sqlca_t *sqlca = ECPGget_sqlca();
|
||||
|
||||
int sqlcode;
|
||||
int sqlcode;
|
||||
|
||||
/* these are not warnings */
|
||||
if (strncmp(sqlstate, "00", 2)==0)
|
||||
if (strncmp(sqlstate, "00", 2) == 0)
|
||||
return;
|
||||
|
||||
ECPGlog("%s", message);
|
||||
|
||||
/* map to SQLCODE for backward compatibility */
|
||||
if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME)==0)
|
||||
if (strcmp(sqlstate, ECPG_SQLSTATE_INVALID_CURSOR_NAME) == 0)
|
||||
sqlcode = ECPG_WARNING_UNKNOWN_PORTAL;
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION)==0)
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION) == 0)
|
||||
sqlcode = ECPG_WARNING_IN_TRANSACTION;
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION)==0)
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION) == 0)
|
||||
sqlcode = ECPG_WARNING_NO_TRANSACTION;
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR)==0)
|
||||
else if (strcmp(sqlstate, ECPG_SQLSTATE_DUPLICATE_CURSOR) == 0)
|
||||
sqlcode = ECPG_WARNING_PORTAL_EXISTS;
|
||||
else
|
||||
sqlcode = 0;
|
||||
@@ -210,21 +210,23 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
|
||||
*options = NULL;
|
||||
|
||||
ECPGinit_sqlca(sqlca);
|
||||
|
||||
|
||||
if (INFORMIX_MODE(compat))
|
||||
{
|
||||
char *envname;
|
||||
|
||||
/* Informix uses an environment variable DBPATH that overrides
|
||||
* the connection parameters given here.
|
||||
* We do the same with PG_DBPATH as the syntax is different. */
|
||||
char *envname;
|
||||
|
||||
/*
|
||||
* Informix uses an environment variable DBPATH that overrides the
|
||||
* connection parameters given here. We do the same with PG_DBPATH
|
||||
* as the syntax is different.
|
||||
*/
|
||||
envname = getenv("PG_DBPATH");
|
||||
if (envname)
|
||||
{
|
||||
ECPGfree(dbname);
|
||||
dbname = strdup(envname);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
|
||||
@@ -378,21 +380,21 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
|
||||
|
||||
if (PQstatus(this->connection) == CONNECTION_BAD)
|
||||
{
|
||||
const char *errmsg = PQerrorMessage(this->connection);
|
||||
char *db = realname ? realname : "<DEFAULT>";
|
||||
const char *errmsg = PQerrorMessage(this->connection);
|
||||
char *db = realname ? realname : "<DEFAULT>";
|
||||
|
||||
ecpg_finish(this);
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_unlock(&connections_mutex);
|
||||
#endif
|
||||
ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n",
|
||||
db,
|
||||
db,
|
||||
host ? host : "<DEFAULT>",
|
||||
port ? port : "<DEFAULT>",
|
||||
options ? "with options " : "", options ? options : "",
|
||||
user ? "for user " : "", user ? user : "",
|
||||
lineno, errmsg);
|
||||
|
||||
|
||||
ECPGraise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
|
||||
if (host)
|
||||
ECPGfree(host);
|
||||
@@ -455,14 +457,14 @@ ECPGdisconnect(int lineno, const char *connection_name)
|
||||
con = ecpg_get_connection_nr(connection_name);
|
||||
|
||||
if (!ECPGinit(con, connection_name, lineno))
|
||||
{
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_unlock(&connections_mutex);
|
||||
pthread_mutex_unlock(&connections_mutex);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
ecpg_finish(con);
|
||||
ecpg_finish(con);
|
||||
}
|
||||
|
||||
#ifdef USE_THREADS
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.15 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.16 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
#include "postgres_fe.h"
|
||||
@@ -24,7 +24,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
{
|
||||
struct sqlca_t *sqlca = ECPGget_sqlca();
|
||||
char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
|
||||
int value_for_indicator = 0;
|
||||
int value_for_indicator = 0;
|
||||
|
||||
ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset);
|
||||
|
||||
@@ -54,11 +54,12 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
/* We will have to decode the value */
|
||||
|
||||
/*
|
||||
* check for null value and set indicator accordingly, i.e. -1 if NULL and 0 if not
|
||||
* check for null value and set indicator accordingly, i.e. -1 if NULL
|
||||
* and 0 if not
|
||||
*/
|
||||
if (PQgetisnull(results, act_tuple, act_field))
|
||||
value_for_indicator = -1;
|
||||
|
||||
|
||||
switch (ind_type)
|
||||
{
|
||||
case ECPGt_short:
|
||||
@@ -81,11 +82,13 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
#endif /* HAVE_LONG_LONG_INT_64 */
|
||||
case ECPGt_NO_INDICATOR:
|
||||
if (value_for_indicator == -1)
|
||||
{
|
||||
{
|
||||
if (force_indicator == false)
|
||||
{
|
||||
/* Informix has an additional way to specify NULLs
|
||||
* note that this uses special values to denote NULL */
|
||||
/*
|
||||
* Informix has an additional way to specify NULLs
|
||||
* note that this uses special values to denote NULL
|
||||
*/
|
||||
ECPGset_informix_null(type, var + offset * act_tuple);
|
||||
}
|
||||
else
|
||||
@@ -109,13 +112,13 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
switch (type)
|
||||
{
|
||||
long res;
|
||||
unsigned long ures;
|
||||
unsigned long ures;
|
||||
double dres;
|
||||
char *scan_length;
|
||||
Numeric *nres;
|
||||
char *scan_length;
|
||||
Numeric *nres;
|
||||
Date ddres;
|
||||
Timestamp tres;
|
||||
Interval *ires;
|
||||
Interval *ires;
|
||||
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
@@ -294,9 +297,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
case ECPGt_unsigned_char:
|
||||
{
|
||||
if (varcharsize == 0)
|
||||
{
|
||||
strncpy((char *) ((long) var + offset * act_tuple), pval, strlen(pval)+1);
|
||||
}
|
||||
strncpy((char *) ((long) var + offset * act_tuple), pval, strlen(pval) + 1);
|
||||
else
|
||||
{
|
||||
strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize);
|
||||
@@ -340,9 +341,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
|
||||
variable->len = strlen(pval);
|
||||
if (varcharsize == 0)
|
||||
{
|
||||
strncpy(variable->arr, pval, variable->len);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(variable->arr, pval, varcharsize);
|
||||
@@ -403,12 +402,12 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
else
|
||||
nres = PGTYPESnumeric_from_asc("0.0", &scan_length);
|
||||
|
||||
if (type == ECPGt_numeric)
|
||||
PGTYPESnumeric_copy(nres, (Numeric *)(var + offset * act_tuple));
|
||||
if (type == ECPGt_numeric)
|
||||
PGTYPESnumeric_copy(nres, (Numeric *) (var + offset * act_tuple));
|
||||
else
|
||||
PGTYPESnumeric_to_decimal(nres, (Decimal *)(var + offset * act_tuple));
|
||||
PGTYPESnumeric_to_decimal(nres, (Decimal *) (var + offset * act_tuple));
|
||||
break;
|
||||
|
||||
|
||||
case ECPGt_interval:
|
||||
if (pval)
|
||||
{
|
||||
@@ -430,7 +429,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
else
|
||||
ires = PGTYPESinterval_from_asc("0 seconds", NULL);
|
||||
|
||||
PGTYPESinterval_copy(ires, (Interval *)(var + offset * act_tuple));
|
||||
PGTYPESinterval_copy(ires, (Interval *) (var + offset * act_tuple));
|
||||
break;
|
||||
case ECPGt_date:
|
||||
if (pval)
|
||||
@@ -450,7 +449,7 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
return (false);
|
||||
}
|
||||
|
||||
*((Date *)(var + offset * act_tuple)) = ddres;
|
||||
*((Date *) (var + offset * act_tuple)) = ddres;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -472,10 +471,10 @@ ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
return (false);
|
||||
}
|
||||
|
||||
*((Timestamp *)(var + offset * act_tuple)) = tres;
|
||||
*((Timestamp *) (var + offset * act_tuple)) = tres;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(type));
|
||||
return (false);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* dynamic SQL support routines
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.5 2003/08/01 13:53:36 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.6 2003/08/04 00:43:32 momjian Exp $
|
||||
*/
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
@@ -454,7 +454,7 @@ ECPGdescriptor_lvalue(int line, const char *descriptor)
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGdescribe(int line, bool input, const char *statement, ...)
|
||||
ECPGdescribe(int line, bool input, const char *statement,...)
|
||||
{
|
||||
ECPGlog("ECPGdescribe called on line %d for %s in %s\n", line, (input) ? "input" : "output", statement);
|
||||
return false;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.5 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.6 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
#include "postgres_fe.h"
|
||||
@@ -13,9 +13,10 @@
|
||||
|
||||
|
||||
void
|
||||
ECPGraise(int line, int code, const char * sqlstate, const char *str)
|
||||
ECPGraise(int line, int code, const char *sqlstate, const char *str)
|
||||
{
|
||||
struct sqlca_t *sqlca = ECPGget_sqlca();
|
||||
|
||||
sqlca->sqlcode = code;
|
||||
strncpy(sqlca->sqlstate, sqlstate, sizeof(sqlca->sqlstate));
|
||||
|
||||
@@ -161,8 +162,8 @@ ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat)
|
||||
|
||||
/* copy error message */
|
||||
snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
|
||||
"'%s' in line %d.",
|
||||
result ? PQresultErrorField(result, 'M') : PQerrorMessage(conn),
|
||||
"'%s' in line %d.",
|
||||
result ? PQresultErrorField(result, 'M') : PQerrorMessage(conn),
|
||||
line);
|
||||
sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
|
||||
|
||||
@@ -172,9 +173,9 @@ ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat)
|
||||
sizeof(sqlca->sqlstate));
|
||||
|
||||
/* assign SQLCODE for backward compatibility */
|
||||
if (strncmp(sqlca->sqlstate, "23505", sizeof(sqlca->sqlstate))==0)
|
||||
if (strncmp(sqlca->sqlstate, "23505", sizeof(sqlca->sqlstate)) == 0)
|
||||
sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_DUPLICATE_KEY : ECPG_DUPLICATE_KEY;
|
||||
if (strncmp(sqlca->sqlstate, "21000", sizeof(sqlca->sqlstate))==0)
|
||||
if (strncmp(sqlca->sqlstate, "21000", sizeof(sqlca->sqlstate)) == 0)
|
||||
sqlca->sqlcode = INFORMIX_MODE(compat) ? ECPG_INFORMIX_SUBSELECT_NOT_ONE : ECPG_SUBSELECT_NOT_ONE;
|
||||
else
|
||||
sqlca->sqlcode = ECPG_PGSQL;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.22 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.23 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
/*
|
||||
* The aim is to get a simpler inteface to the database routines.
|
||||
@@ -65,7 +65,7 @@ quote_postgres(char *arg, int lineno)
|
||||
|
||||
res[ri++] = '\'';
|
||||
res[ri] = '\0';
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -138,13 +138,16 @@ create_statement(int lineno, int compat, int force_indicator, struct connection
|
||||
else
|
||||
var->value = var->pointer;
|
||||
|
||||
/* negative values are used to indicate an array without given bounds */
|
||||
/*
|
||||
* negative values are used to indicate an array without given
|
||||
* bounds
|
||||
*/
|
||||
/* reset to zero for us */
|
||||
if (var->arrsize < 0)
|
||||
var->arrsize = 0;
|
||||
if (var->varcharsize < 0)
|
||||
var->varcharsize = 0;
|
||||
|
||||
|
||||
var->ind_type = va_arg(ap, enum ECPGttype);
|
||||
var->ind_pointer = va_arg(ap, char *);
|
||||
var->ind_varcharsize = va_arg(ap, long);
|
||||
@@ -157,8 +160,11 @@ create_statement(int lineno, int compat, int force_indicator, struct connection
|
||||
var->ind_value = *((char **) (var->ind_pointer));
|
||||
else
|
||||
var->ind_value = var->ind_pointer;
|
||||
|
||||
/* negative values are used to indicate an array without given bounds */
|
||||
|
||||
/*
|
||||
* negative values are used to indicate an array without given
|
||||
* bounds
|
||||
*/
|
||||
/* reset to zero for us */
|
||||
if (var->ind_arrsize < 0)
|
||||
var->ind_arrsize = 0;
|
||||
@@ -482,11 +488,11 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
* we do not know if the attribute is an array here
|
||||
*/
|
||||
#if 0
|
||||
if (var->arrsize > 1 && ...)
|
||||
{
|
||||
if (var->arrsize > 1 &&...)
|
||||
{
|
||||
ECPGraise(stmt->lineno, ECPG_ARRAY_INSERT, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -739,7 +745,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
break;
|
||||
|
||||
case ECPGt_bool:
|
||||
if (!(mallocedval = ECPGalloc(var->arrsize +sizeof ("array []"), stmt->lineno)))
|
||||
if (!(mallocedval = ECPGalloc(var->arrsize + sizeof("array []"), stmt->lineno)))
|
||||
return false;
|
||||
|
||||
if (var->arrsize > 1)
|
||||
@@ -838,30 +844,30 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
case ECPGt_decimal:
|
||||
case ECPGt_numeric:
|
||||
{
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
Numeric *nval = PGTYPESnumeric_new();
|
||||
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
Numeric *nval = PGTYPESnumeric_new();
|
||||
|
||||
if (var->arrsize > 1)
|
||||
{
|
||||
for (element = 0; element < var->arrsize; element++)
|
||||
{
|
||||
if (var->type == ECPGt_numeric)
|
||||
PGTYPESnumeric_copy((Numeric *)((var + var->offset * element)->value), nval);
|
||||
PGTYPESnumeric_copy((Numeric *) ((var + var->offset * element)->value), nval);
|
||||
else
|
||||
PGTYPESnumeric_from_decimal((Decimal *)((var + var->offset * element)->value), nval);
|
||||
|
||||
PGTYPESnumeric_from_decimal((Decimal *) ((var + var->offset * element)->value), nval);
|
||||
|
||||
str = PGTYPESnumeric_to_asc(nval, 0);
|
||||
PGTYPESnumeric_free(nval);
|
||||
slen = strlen (str);
|
||||
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [] "), stmt->lineno)))
|
||||
return false;
|
||||
|
||||
|
||||
if (!element)
|
||||
strcpy(mallocedval, "array [");
|
||||
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||
}
|
||||
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
|
||||
@@ -869,22 +875,22 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
else
|
||||
{
|
||||
if (var->type == ECPGt_numeric)
|
||||
PGTYPESnumeric_copy((Numeric *)(var->value), nval);
|
||||
PGTYPESnumeric_copy((Numeric *) (var->value), nval);
|
||||
else
|
||||
PGTYPESnumeric_from_decimal((Decimal *)(var->value), nval);
|
||||
|
||||
PGTYPESnumeric_from_decimal((Decimal *) (var->value), nval);
|
||||
|
||||
str = PGTYPESnumeric_to_asc(nval, 0);
|
||||
|
||||
PGTYPESnumeric_free(nval);
|
||||
slen = strlen (str);
|
||||
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
|
||||
return false;
|
||||
|
||||
strncpy(mallocedval, str , slen);
|
||||
strncpy(mallocedval, str, slen);
|
||||
mallocedval[slen] = '\0';
|
||||
}
|
||||
|
||||
|
||||
*tobeinserted_p = mallocedval;
|
||||
*malloced_p = true;
|
||||
free(str);
|
||||
@@ -893,41 +899,41 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
|
||||
case ECPGt_interval:
|
||||
{
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
if (var->arrsize > 1)
|
||||
{
|
||||
for (element = 0; element < var->arrsize; element++)
|
||||
{
|
||||
str = quote_postgres(PGTYPESinterval_to_asc((Interval *)((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPESinterval_to_asc((Interval *) ((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],interval "), stmt->lineno)))
|
||||
return false;
|
||||
|
||||
|
||||
if (!element)
|
||||
strcpy(mallocedval, "array [");
|
||||
|
||||
|
||||
strcpy(mallocedval + strlen(mallocedval), "interval ");
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||
}
|
||||
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
str = quote_postgres(PGTYPESinterval_to_asc((Interval *)(var->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPESinterval_to_asc((Interval *) (var->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGalloc(slen + sizeof("interval ") + 1, stmt->lineno)))
|
||||
return false;
|
||||
|
||||
strcpy(mallocedval, "interval ");
|
||||
/* also copy trailing '\0' */
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
}
|
||||
|
||||
|
||||
*tobeinserted_p = mallocedval;
|
||||
*malloced_p = true;
|
||||
free(str);
|
||||
@@ -936,90 +942,90 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
|
||||
|
||||
case ECPGt_date:
|
||||
{
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
if (var->arrsize > 1)
|
||||
{
|
||||
for (element = 0; element < var->arrsize; element++)
|
||||
{
|
||||
str = quote_postgres(PGTYPESdate_to_asc(*(Date *)((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPESdate_to_asc(*(Date *) ((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [],date "), stmt->lineno)))
|
||||
return false;
|
||||
|
||||
|
||||
if (!element)
|
||||
strcpy(mallocedval, "array [");
|
||||
|
||||
|
||||
strcpy(mallocedval + strlen(mallocedval), "date ");
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||
}
|
||||
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
str = quote_postgres(PGTYPESdate_to_asc(*(Date *)(var->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPESdate_to_asc(*(Date *) (var->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGalloc(slen + sizeof("date ") + 1, stmt->lineno)))
|
||||
return false;
|
||||
|
||||
strcpy(mallocedval, "date ");
|
||||
/* also copy trailing '\0' */
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
}
|
||||
|
||||
|
||||
*tobeinserted_p = mallocedval;
|
||||
*malloced_p = true;
|
||||
free(str);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ECPGt_timestamp:
|
||||
{
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
char *str = NULL;
|
||||
int slen;
|
||||
|
||||
if (var->arrsize > 1)
|
||||
{
|
||||
for (element = 0; element < var->arrsize; element++)
|
||||
{
|
||||
str = quote_postgres(PGTYPEStimestamp_to_asc(*(Timestamp *)((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPEStimestamp_to_asc(*(Timestamp *) ((var + var->offset * element)->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGrealloc(mallocedval, strlen(mallocedval) + slen + sizeof("array [], timestamp "), stmt->lineno)))
|
||||
return false;
|
||||
|
||||
|
||||
if (!element)
|
||||
strcpy(mallocedval, "array [");
|
||||
|
||||
|
||||
strcpy(mallocedval + strlen(mallocedval), "timestamp ");
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
strcpy(mallocedval + strlen(mallocedval), ",");
|
||||
}
|
||||
strcpy(mallocedval + strlen(mallocedval) - 1, "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
str = quote_postgres(PGTYPEStimestamp_to_asc(*(Timestamp *)(var->value)), stmt->lineno);
|
||||
slen = strlen (str);
|
||||
|
||||
str = quote_postgres(PGTYPEStimestamp_to_asc(*(Timestamp *) (var->value)), stmt->lineno);
|
||||
slen = strlen(str);
|
||||
|
||||
if (!(mallocedval = ECPGalloc(slen + sizeof("timestamp") + 1, stmt->lineno)))
|
||||
return false;
|
||||
|
||||
strcpy(mallocedval, "timestamp ");
|
||||
/* also copy trailing '\0' */
|
||||
strncpy(mallocedval + strlen(mallocedval), str , slen + 1);
|
||||
strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
|
||||
}
|
||||
|
||||
|
||||
*tobeinserted_p = mallocedval;
|
||||
*malloced_p = true;
|
||||
free(str);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Not implemented yet */
|
||||
ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (char *) ECPGtype_name(var->type));
|
||||
@@ -1219,10 +1225,10 @@ ECPGexecute(struct statement * stmt)
|
||||
sqlca->sqlerrd[2] = atol(PQcmdTuples(results));
|
||||
ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, cmdstat);
|
||||
if (stmt->compat != ECPG_COMPAT_INFORMIX_SE &&
|
||||
!sqlca->sqlerrd[2] &&
|
||||
( !strncmp(cmdstat, "UPDATE", 6)
|
||||
|| !strncmp(cmdstat, "INSERT", 6)
|
||||
|| !strncmp(cmdstat, "DELETE", 6)))
|
||||
!sqlca->sqlerrd[2] &&
|
||||
(!strncmp(cmdstat, "UPDATE", 6)
|
||||
|| !strncmp(cmdstat, "INSERT", 6)
|
||||
|| !strncmp(cmdstat, "DELETE", 6)))
|
||||
ECPGraise(stmt->lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL);
|
||||
break;
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
@@ -1326,4 +1332,3 @@ ECPGdo_descriptor(int line, const char *connection,
|
||||
ECPGt_descriptor, descriptor, 0L, 0L, 0L,
|
||||
ECPGt_NO_INDICATOR, NULL, 0L, 0L, 0L, ECPGt_EORT);
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,11 @@
|
||||
#include "libpq-fe.h"
|
||||
#include "sqlca.h"
|
||||
|
||||
enum COMPAT_MODE { ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE};
|
||||
enum COMPAT_MODE
|
||||
{
|
||||
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
|
||||
};
|
||||
|
||||
#define INFORMIX_MODE(X) ((X) == ECPG_COMPAT_INFORMIX || (X) == ECPG_COMPAT_INFORMIX_SE)
|
||||
|
||||
/* Here are some methods used by the lib. */
|
||||
@@ -51,7 +55,7 @@ struct statement
|
||||
char *command;
|
||||
struct connection *connection;
|
||||
enum COMPAT_MODE compat;
|
||||
bool force_indicator;
|
||||
bool force_indicator;
|
||||
struct variable *inlist;
|
||||
struct variable *outlist;
|
||||
};
|
||||
@@ -109,7 +113,7 @@ bool ECPGstore_result(const PGresult *results, int act_field,
|
||||
#define ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION "08001"
|
||||
#define ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST "08003"
|
||||
#define ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN "08007"
|
||||
#define ECPG_SQLSTATE_CARDINALITY_VIOLATION "21000"
|
||||
#define ECPG_SQLSTATE_CARDINALITY_VIOLATION "21000"
|
||||
#define ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER "22002"
|
||||
#define ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION "25001"
|
||||
#define ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION "25P01"
|
||||
@@ -124,4 +128,4 @@ bool ECPGstore_result(const PGresult *results, int act_field,
|
||||
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR "YE000"
|
||||
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY "YE001"
|
||||
|
||||
#endif /* _ECPG_LIB_EXTERN_H */
|
||||
#endif /* _ECPG_LIB_EXTERN_H */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.12 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.13 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
#include "postgres_fe.h"
|
||||
@@ -23,7 +23,7 @@
|
||||
#define LONG_LONG_MIN LLONG_MIN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static struct sqlca_t sqlca_init =
|
||||
{
|
||||
{
|
||||
@@ -52,8 +52,9 @@ static struct sqlca_t sqlca_init =
|
||||
};
|
||||
|
||||
#ifdef USE_THREADS
|
||||
static pthread_key_t sqlca_key;
|
||||
static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
|
||||
static pthread_key_t sqlca_key;
|
||||
static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
#else
|
||||
static struct sqlca_t sqlca =
|
||||
{
|
||||
@@ -84,22 +85,23 @@ static struct sqlca_t sqlca =
|
||||
#endif
|
||||
|
||||
#ifdef USE_THREADS
|
||||
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
static int simple_debug = 0;
|
||||
static int simple_debug = 0;
|
||||
static FILE *debugstream = NULL;
|
||||
|
||||
void
|
||||
ECPGinit_sqlca(struct sqlca_t *sqlca)
|
||||
ECPGinit_sqlca(struct sqlca_t * sqlca)
|
||||
{
|
||||
memcpy((char *)sqlca, (char *)&sqlca_init, sizeof(struct sqlca_t));
|
||||
memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
|
||||
{
|
||||
struct sqlca_t *sqlca = ECPGget_sqlca();
|
||||
|
||||
ECPGinit_sqlca(sqlca);
|
||||
if (con == NULL)
|
||||
{
|
||||
@@ -115,7 +117,7 @@ ECPGinit(const struct connection * con, const char *connection_name, const int l
|
||||
static void
|
||||
ecpg_sqlca_key_init(void)
|
||||
{
|
||||
pthread_key_create(&sqlca_key, NULL);
|
||||
pthread_key_create(&sqlca_key, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -123,20 +125,20 @@ struct sqlca_t *
|
||||
ECPGget_sqlca(void)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
struct sqlca_t *sqlca;
|
||||
struct sqlca_t *sqlca;
|
||||
|
||||
pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
|
||||
pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
|
||||
|
||||
sqlca = pthread_getspecific(sqlca_key);
|
||||
if( sqlca == NULL )
|
||||
{
|
||||
sqlca = malloc(sizeof(struct sqlca_t));
|
||||
ECPGinit_sqlca(sqlca);
|
||||
pthread_setspecific(sqlca_key, sqlca);
|
||||
}
|
||||
return( sqlca );
|
||||
sqlca = pthread_getspecific(sqlca_key);
|
||||
if (sqlca == NULL)
|
||||
{
|
||||
sqlca = malloc(sizeof(struct sqlca_t));
|
||||
ECPGinit_sqlca(sqlca);
|
||||
pthread_setspecific(sqlca_key, sqlca);
|
||||
}
|
||||
return (sqlca);
|
||||
#else
|
||||
return( &sqlca );
|
||||
return (&sqlca);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -227,16 +229,17 @@ ECPGlog(const char *format,...)
|
||||
pthread_mutex_lock(&debug_mutex);
|
||||
#endif
|
||||
|
||||
if( simple_debug )
|
||||
if (simple_debug)
|
||||
{
|
||||
char *f = (char *)malloc(strlen(format) + 100);
|
||||
if( f == NULL )
|
||||
{
|
||||
char *f = (char *) malloc(strlen(format) + 100);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
pthread_mutex_unlock(&debug_mutex);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(f, "[%d]: %s", (int) getpid(), format);
|
||||
|
||||
@@ -258,7 +261,7 @@ ECPGset_informix_null(enum ECPGttype type, void *ptr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_char:
|
||||
case ECPGt_char:
|
||||
case ECPGt_unsigned_char:
|
||||
*((char *) ptr) = 0x00;
|
||||
break;
|
||||
@@ -307,10 +310,12 @@ ECPGset_informix_null(enum ECPGttype type, void *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
static bool _check(unsigned char *ptr, int length)
|
||||
static bool
|
||||
_check(unsigned char *ptr, int length)
|
||||
{
|
||||
for (;ptr[--length] == 0xff && length >= 0; length --);
|
||||
if (length < 0) return true;
|
||||
for (; ptr[--length] == 0xff && length >= 0; length--);
|
||||
if (length < 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -319,49 +324,57 @@ ECPGis_informix_null(enum ECPGttype type, void *ptr)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_char:
|
||||
case ECPGt_char:
|
||||
case ECPGt_unsigned_char:
|
||||
if (*((char *)ptr) == 0x00) return true;
|
||||
if (*((char *) ptr) == 0x00)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_short:
|
||||
case ECPGt_unsigned_short:
|
||||
if (*((short int *) ptr) == SHRT_MIN) return true;
|
||||
if (*((short int *) ptr) == SHRT_MIN)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_int:
|
||||
case ECPGt_unsigned_int:
|
||||
if (*((int *) ptr) == INT_MIN) return true;
|
||||
if (*((int *) ptr) == INT_MIN)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_long:
|
||||
case ECPGt_unsigned_long:
|
||||
case ECPGt_date:
|
||||
if (*((long *) ptr) == LONG_MIN) return true;
|
||||
if (*((long *) ptr) == LONG_MIN)
|
||||
return true;
|
||||
break;
|
||||
#ifdef HAVE_LONG_LONG_INT_64
|
||||
case ECPGt_long_long:
|
||||
case ECPGt_unsigned_long_long:
|
||||
if (*((long long *) ptr) == LONG_LONG_MIN) return true;
|
||||
if (*((long long *) ptr) == LONG_LONG_MIN)
|
||||
return true;
|
||||
break;
|
||||
#endif /* HAVE_LONG_LONG_INT_64 */
|
||||
case ECPGt_float:
|
||||
return(_check(ptr, sizeof(float)));
|
||||
return (_check(ptr, sizeof(float)));
|
||||
break;
|
||||
case ECPGt_double:
|
||||
return(_check(ptr, sizeof(double)));
|
||||
return (_check(ptr, sizeof(double)));
|
||||
break;
|
||||
case ECPGt_varchar:
|
||||
if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00) return true;
|
||||
if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_decimal:
|
||||
if (((Decimal *) ptr)->sign == NUMERIC_NAN) return true;
|
||||
if (((Decimal *) ptr)->sign == NUMERIC_NAN)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_numeric:
|
||||
if (((Numeric *) ptr)->sign == NUMERIC_NAN) return true;
|
||||
if (((Numeric *) ptr)->sign == NUMERIC_NAN)
|
||||
return true;
|
||||
break;
|
||||
case ECPGt_interval:
|
||||
return(_check(ptr, sizeof(Interval)));
|
||||
return (_check(ptr, sizeof(Interval)));
|
||||
break;
|
||||
case ECPGt_timestamp:
|
||||
return(_check(ptr, sizeof(Timestamp)));
|
||||
return (_check(ptr, sizeof(Timestamp)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.8 2003/08/01 13:53:36 petere Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.9 2003/08/04 00:43:32 momjian Exp $ */
|
||||
|
||||
#define POSTGRES_ECPG_INTERNAL
|
||||
#include "postgres_fe.h"
|
||||
@@ -66,7 +66,7 @@ ECPGprepare(int lineno, char *name, char *variable)
|
||||
for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
|
||||
if (this)
|
||||
{
|
||||
bool b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, name);
|
||||
bool b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, name);
|
||||
|
||||
if (!b)
|
||||
return false;
|
||||
@@ -109,17 +109,19 @@ ECPGprepare(int lineno, char *name, char *variable)
|
||||
bool
|
||||
ECPGdeallocate(int lineno, int c, char *name)
|
||||
{
|
||||
bool ret = ECPGdeallocate_one(lineno, name);
|
||||
bool ret = ECPGdeallocate_one(lineno, name);
|
||||
enum COMPAT_MODE compat = c;
|
||||
|
||||
if (INFORMIX_MODE(compat))
|
||||
{
|
||||
/* Just ignore all errors since we do not know the list of cursors we
|
||||
* are allowed to free. We have to trust that the software. */
|
||||
return true;
|
||||
/*
|
||||
* Just ignore all errors since we do not know the list of cursors
|
||||
* we are allowed to free. We have to trust that the software.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
|
||||
if (!ret)
|
||||
ECPGraise(lineno, ECPG_INVALID_STMT, ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME, name);
|
||||
|
||||
return ret;
|
||||
@@ -156,7 +158,7 @@ ECPGdeallocate_all(int lineno)
|
||||
/* deallocate all prepared statements */
|
||||
while (prep_stmts != NULL)
|
||||
{
|
||||
bool b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, prep_stmts->name);
|
||||
bool b = ECPGdeallocate(lineno, ECPG_COMPAT_PGSQL, prep_stmts->name);
|
||||
|
||||
if (!b)
|
||||
return false;
|
||||
|
@@ -3,16 +3,16 @@
|
||||
|
||||
#ifndef dtime_t
|
||||
#define dtime_t Timestamp
|
||||
#endif /* dtime_t */
|
||||
#endif /* dtime_t */
|
||||
|
||||
#ifndef intrvl_t
|
||||
#define intrvl_t Interval
|
||||
#endif /* intrvl_t */
|
||||
#endif /* intrvl_t */
|
||||
|
||||
extern void dtcurrent (dtime_t *);
|
||||
extern int dtcvasc (char *, dtime_t *);
|
||||
extern int dtsub (dtime_t *, dtime_t *, intrvl_t *);
|
||||
extern int dttoasc (dtime_t *, char *);
|
||||
extern int dttofmtasc (dtime_t *, char *, int, char *);
|
||||
extern int intoasc(intrvl_t *, char *);
|
||||
extern int dtcvfmtasc(char *, char *, dtime_t *);
|
||||
extern void dtcurrent(dtime_t *);
|
||||
extern int dtcvasc(char *, dtime_t *);
|
||||
extern int dtsub(dtime_t *, dtime_t *, intrvl_t *);
|
||||
extern int dttoasc(dtime_t *, char *);
|
||||
extern int dttofmtasc(dtime_t *, char *, int, char *);
|
||||
extern int intoasc(intrvl_t *, char *);
|
||||
extern int dtcvfmtasc(char *, char *, dtime_t *);
|
||||
|
@@ -2,20 +2,19 @@
|
||||
|
||||
#ifndef dec_t
|
||||
#define dec_t Decimal
|
||||
#endif /* dec_t */
|
||||
|
||||
int decadd(dec_t *, dec_t *, dec_t *);
|
||||
int deccmp(dec_t *, dec_t *);
|
||||
void deccopy(dec_t *, dec_t *);
|
||||
int deccvasc(char *, int, dec_t *);
|
||||
int deccvdbl(double, dec_t *);
|
||||
int deccvint(int, dec_t *);
|
||||
int deccvlong(long, dec_t *);
|
||||
int decdiv(dec_t *, dec_t *, dec_t *);
|
||||
int decmul(dec_t *, dec_t *, dec_t *);
|
||||
int decsub(dec_t *, dec_t *, dec_t *);
|
||||
int dectoasc(dec_t *, char *, int, int);
|
||||
int dectodbl(dec_t *, double *);
|
||||
int dectoint(dec_t *, int *);
|
||||
int dectolong(dec_t *, long *);
|
||||
#endif /* dec_t */
|
||||
|
||||
int decadd(dec_t *, dec_t *, dec_t *);
|
||||
int deccmp(dec_t *, dec_t *);
|
||||
void deccopy(dec_t *, dec_t *);
|
||||
int deccvasc(char *, int, dec_t *);
|
||||
int deccvdbl(double, dec_t *);
|
||||
int deccvint(int, dec_t *);
|
||||
int deccvlong(long, dec_t *);
|
||||
int decdiv(dec_t *, dec_t *, dec_t *);
|
||||
int decmul(dec_t *, dec_t *, dec_t *);
|
||||
int decsub(dec_t *, dec_t *, dec_t *);
|
||||
int dectoasc(dec_t *, char *, int, int);
|
||||
int dectodbl(dec_t *, double *);
|
||||
int dectoint(dec_t *, int *);
|
||||
int dectolong(dec_t *, long *);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* This file contains stuff needed to be as compatible to Informix as possible.
|
||||
*/
|
||||
|
||||
@@ -10,27 +10,27 @@
|
||||
|
||||
#ifndef Date
|
||||
#define Date long
|
||||
#endif /* ! Date */
|
||||
#endif /* ! Date */
|
||||
|
||||
extern int rdatestr (Date, char *);
|
||||
extern void rtoday (Date *);
|
||||
extern int rjulmdy (Date, short *);
|
||||
extern int rdefmtdate (Date *, char *, char *);
|
||||
extern int rfmtdate (Date, char *, char *);
|
||||
extern int rmdyjul (short *, Date *);
|
||||
extern int rstrdate (char *, Date *);
|
||||
extern int rdayofweek(Date);
|
||||
extern int rdatestr(Date, char *);
|
||||
extern void rtoday(Date *);
|
||||
extern int rjulmdy(Date, short *);
|
||||
extern int rdefmtdate(Date *, char *, char *);
|
||||
extern int rfmtdate(Date, char *, char *);
|
||||
extern int rmdyjul(short *, Date *);
|
||||
extern int rstrdate(char *, Date *);
|
||||
extern int rdayofweek(Date);
|
||||
|
||||
extern int rfmtlong(long, char *, char *);
|
||||
extern int rgetmsg(int, char *, int);
|
||||
extern int risnull(int, char *);
|
||||
extern int rsetnull(int, char *);
|
||||
extern int rtypalign(int, int);
|
||||
extern int rtypmsize(int, int);
|
||||
extern int rtypwidth(int, int);
|
||||
extern int rfmtlong(long, char *, char *);
|
||||
extern int rgetmsg(int, char *, int);
|
||||
extern int risnull(int, char *);
|
||||
extern int rsetnull(int, char *);
|
||||
extern int rtypalign(int, int);
|
||||
extern int rtypmsize(int, int);
|
||||
extern int rtypwidth(int, int);
|
||||
extern void rupshift(char *);
|
||||
|
||||
extern int byleng(char *, int);
|
||||
extern int byleng(char *, int);
|
||||
extern void ldchar(char *, int, char *);
|
||||
|
||||
extern void ECPG_informix_set_var(int, void *, int);
|
||||
|
@@ -52,8 +52,8 @@
|
||||
|
||||
/* for compatibility we define some different error codes for the same error
|
||||
* if adding a new one make sure to not double define it */
|
||||
#define ECPG_INFORMIX_DUPLICATE_KEY -239
|
||||
#define ECPG_INFORMIX_SUBSELECT_NOT_ONE -284
|
||||
#define ECPG_INFORMIX_DUPLICATE_KEY -239
|
||||
#define ECPG_INFORMIX_SUBSELECT_NOT_ONE -284
|
||||
|
||||
/* backend WARNINGs, starting at 600 */
|
||||
#define ECPG_WARNING_UNRECOGNIZED -600
|
||||
|
@@ -41,7 +41,7 @@ extern "C"
|
||||
|
||||
struct sqlca_t;
|
||||
|
||||
void ECPGinit_sqlca(struct sqlca_t *sqlca);
|
||||
void ECPGinit_sqlca(struct sqlca_t * sqlca);
|
||||
void ECPGdebug(int, FILE *);
|
||||
bool ECPGstatus(int, const char *);
|
||||
bool ECPGsetcommit(int, const char *, const char *);
|
||||
@@ -57,7 +57,7 @@ bool ECPGdeallocate_all(int);
|
||||
char *ECPGprepared_statement(char *);
|
||||
|
||||
void ECPGlog(const char *format,...);
|
||||
char *ECPGerrmsg(void);
|
||||
char *ECPGerrmsg(void);
|
||||
|
||||
/* print an error message */
|
||||
void sqlprint(void);
|
||||
@@ -79,14 +79,13 @@ bool ECPGget_desc(int, char *, int,...);
|
||||
|
||||
void ECPGset_informix_null(enum ECPGttype, void *);
|
||||
bool ECPGis_informix_null(enum ECPGttype, void *);
|
||||
bool ECPGdescribe(int, bool, const char *, ...);
|
||||
bool ECPGdescribe(int, bool, const char *,...);
|
||||
|
||||
/* dynamic result allocation */
|
||||
void ECPGfree_auto_mem(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ECPGLIB_H */
|
||||
#endif /* _ECPGLIB_H */
|
||||
|
@@ -44,20 +44,22 @@ enum ECPGttype
|
||||
ECPGt_bool,
|
||||
ECPGt_float, ECPGt_double,
|
||||
ECPGt_varchar, ECPGt_varchar2,
|
||||
ECPGt_numeric, /* this is a decimal that stores its digits in a malloced array */
|
||||
ECPGt_decimal, /* this is a decimal that stores its digits in a fixed array */
|
||||
ECPGt_numeric, /* this is a decimal that stores its
|
||||
* digits in a malloced array */
|
||||
ECPGt_decimal, /* this is a decimal that stores its
|
||||
* digits in a fixed array */
|
||||
ECPGt_date,
|
||||
ECPGt_timestamp,
|
||||
ECPGt_interval,
|
||||
ECPGt_array,
|
||||
ECPGt_struct,
|
||||
ECPGt_union,
|
||||
ECPGt_descriptor, /* sql descriptor, no C variable */
|
||||
ECPGt_descriptor, /* sql descriptor, no C variable */
|
||||
ECPGt_char_variable,
|
||||
ECPGt_const, /* a constant is needed sometimes */
|
||||
ECPGt_EOIT, /* End of insert types. */
|
||||
ECPGt_EORT, /* End of result types. */
|
||||
ECPGt_NO_INDICATOR /* no indicator */
|
||||
ECPGt_const, /* a constant is needed sometimes */
|
||||
ECPGt_EOIT, /* End of insert types. */
|
||||
ECPGt_EORT, /* End of result types. */
|
||||
ECPGt_NO_INDICATOR /* no indicator */
|
||||
};
|
||||
|
||||
/* descriptor items */
|
||||
@@ -88,4 +90,4 @@ enum ECPGdtype
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ECPGTYPE_H */
|
||||
#endif /* _ECPGTYPE_H */
|
||||
|
@@ -8,10 +8,11 @@
|
||||
extern Date PGTYPESdate_from_asc(char *, char **);
|
||||
extern char *PGTYPESdate_to_asc(Date);
|
||||
extern Date PGTYPESdate_from_timestamp(Timestamp);
|
||||
extern void PGTYPESdate_julmdy(Date, int*);
|
||||
extern void PGTYPESdate_mdyjul(int*, Date *);
|
||||
extern int PGTYPESdate_dayofweek(Date);
|
||||
extern void PGTYPESdate_today (Date *);
|
||||
extern int PGTYPESdate_defmt_asc(Date *, char *, char *);
|
||||
extern int PGTYPESdate_fmt_asc(Date, char *, char *);
|
||||
#endif /* PGTYPES_DATETIME */
|
||||
extern void PGTYPESdate_julmdy(Date, int *);
|
||||
extern void PGTYPESdate_mdyjul(int *, Date *);
|
||||
extern int PGTYPESdate_dayofweek(Date);
|
||||
extern void PGTYPESdate_today(Date *);
|
||||
extern int PGTYPESdate_defmt_asc(Date *, char *, char *);
|
||||
extern int PGTYPESdate_fmt_asc(Date, char *, char *);
|
||||
|
||||
#endif /* PGTYPES_DATETIME */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#define PGTYPES_NUM_OVERFLOW 301
|
||||
#define PGTYPES_NUM_OVERFLOW 301
|
||||
#define PGTYPES_NUM_BAD_NUMERIC 302
|
||||
#define PGTYPES_NUM_DIVIDE_ZERO 303
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#define PGTYPES_DATE_BAD_MONTH 315
|
||||
|
||||
#define PGTYPES_TS_BAD_TIMESTAMP 320
|
||||
#define PGTYPES_TS_ERR_EINFTIME 321
|
||||
#define PGTYPES_TS_ERR_EINFTIME 321
|
||||
|
||||
#define PGTYPES_INTVL_BAD_INTERVAL 330
|
||||
|
||||
|
@@ -4,15 +4,18 @@
|
||||
typedef struct
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 time; /* all time units other than months and years */
|
||||
int64 time; /* all time units other than months and
|
||||
* years */
|
||||
#else
|
||||
double time; /* all time units other than months and years */
|
||||
double time; /* all time units other than months and
|
||||
* years */
|
||||
#endif
|
||||
long month; /* months and years, after time for alignment */
|
||||
long month; /* months and years, after time for
|
||||
* alignment */
|
||||
} Interval;
|
||||
|
||||
extern Interval *PGTYPESinterval_from_asc(char *, char **);
|
||||
extern char *PGTYPESinterval_to_asc(Interval *);
|
||||
extern int PGTYPESinterval_copy(Interval *, Interval *);
|
||||
|
||||
#endif /* PGTYPES_INTERVAL */
|
||||
extern int PGTYPESinterval_copy(Interval *, Interval *);
|
||||
|
||||
#endif /* PGTYPES_INTERVAL */
|
||||
|
@@ -1,55 +1,59 @@
|
||||
#ifndef PGTYPES_NUMERIC
|
||||
#define PGTYPES_NUMERIC
|
||||
|
||||
#define NUMERIC_POS 0x0000
|
||||
#define NUMERIC_NEG 0x4000
|
||||
#define NUMERIC_NAN 0xC000
|
||||
#define NUMERIC_MAX_PRECISION 1000
|
||||
#define NUMERIC_MAX_DISPLAY_SCALE NUMERIC_MAX_PRECISION
|
||||
#define NUMERIC_MIN_DISPLAY_SCALE 0
|
||||
#define NUMERIC_MIN_SIG_DIGITS 16
|
||||
#define NUMERIC_POS 0x0000
|
||||
#define NUMERIC_NEG 0x4000
|
||||
#define NUMERIC_NAN 0xC000
|
||||
#define NUMERIC_MAX_PRECISION 1000
|
||||
#define NUMERIC_MAX_DISPLAY_SCALE NUMERIC_MAX_PRECISION
|
||||
#define NUMERIC_MIN_DISPLAY_SCALE 0
|
||||
#define NUMERIC_MIN_SIG_DIGITS 16
|
||||
|
||||
#define DECSIZE 30
|
||||
|
||||
typedef unsigned char NumericDigit;
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
int ndigits; /* number of digits in digits[] - can be 0! */
|
||||
int weight; /* weight of first digit */
|
||||
int rscale; /* result scale */
|
||||
int dscale; /* display scale */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
|
||||
NumericDigit *buf; /* start of alloc'd space for digits[] */
|
||||
NumericDigit *digits; /* decimal digits */
|
||||
int ndigits; /* number of digits in digits[] - can be
|
||||
* 0! */
|
||||
int weight; /* weight of first digit */
|
||||
int rscale; /* result scale */
|
||||
int dscale; /* display scale */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or
|
||||
* NUMERIC_NAN */
|
||||
NumericDigit *buf; /* start of alloc'd space for digits[] */
|
||||
NumericDigit *digits; /* decimal digits */
|
||||
} Numeric;
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
int ndigits; /* number of digits in digits[] - can be 0! */
|
||||
int weight; /* weight of first digit */
|
||||
int rscale; /* result scale */
|
||||
int dscale; /* display scale */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
|
||||
NumericDigit digits[DECSIZE]; /* decimal digits */
|
||||
} Decimal;
|
||||
int ndigits; /* number of digits in digits[] - can be
|
||||
* 0! */
|
||||
int weight; /* weight of first digit */
|
||||
int rscale; /* result scale */
|
||||
int dscale; /* display scale */
|
||||
int sign; /* NUMERIC_POS, NUMERIC_NEG, or
|
||||
* NUMERIC_NAN */
|
||||
NumericDigit digits[DECSIZE]; /* decimal digits */
|
||||
} Decimal;
|
||||
|
||||
Numeric *PGTYPESnumeric_new(void);
|
||||
void PGTYPESnumeric_free(Numeric *);
|
||||
Numeric *PGTYPESnumeric_from_asc(char *, char **);
|
||||
char *PGTYPESnumeric_to_asc(Numeric *, int);
|
||||
int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_div(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_cmp(Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_from_int(signed int, Numeric *);
|
||||
int PGTYPESnumeric_from_long(signed long int, Numeric *);
|
||||
int PGTYPESnumeric_copy(Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_from_double(double, Numeric *);
|
||||
int PGTYPESnumeric_to_double(Numeric *, double *);
|
||||
int PGTYPESnumeric_to_int(Numeric *, int *);
|
||||
int PGTYPESnumeric_to_long(Numeric *, long *);
|
||||
int PGTYPESnumeric_to_decimal(Numeric *, Decimal *);
|
||||
int PGTYPESnumeric_from_decimal(Decimal *, Numeric *);
|
||||
Numeric *PGTYPESnumeric_new(void);
|
||||
void PGTYPESnumeric_free(Numeric *);
|
||||
Numeric *PGTYPESnumeric_from_asc(char *, char **);
|
||||
char *PGTYPESnumeric_to_asc(Numeric *, int);
|
||||
int PGTYPESnumeric_add(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_sub(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_mul(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_div(Numeric *, Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_cmp(Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_from_int(signed int, Numeric *);
|
||||
int PGTYPESnumeric_from_long(signed long int, Numeric *);
|
||||
int PGTYPESnumeric_copy(Numeric *, Numeric *);
|
||||
int PGTYPESnumeric_from_double(double, Numeric *);
|
||||
int PGTYPESnumeric_to_double(Numeric *, double *);
|
||||
int PGTYPESnumeric_to_int(Numeric *, int *);
|
||||
int PGTYPESnumeric_to_long(Numeric *, long *);
|
||||
int PGTYPESnumeric_to_decimal(Numeric *, Decimal *);
|
||||
int PGTYPESnumeric_from_decimal(Decimal *, Numeric *);
|
||||
|
||||
#endif /* PGTYPES_NUMERIC */
|
||||
#endif /* PGTYPES_NUMERIC */
|
||||
|
@@ -14,9 +14,9 @@ typedef double TimestampTz;
|
||||
|
||||
extern Timestamp PGTYPEStimestamp_from_asc(char *, char **);
|
||||
extern char *PGTYPEStimestamp_to_asc(Timestamp);
|
||||
extern int PGTYPEStimestamp_sub (Timestamp *, Timestamp *, Interval *);
|
||||
extern int PGTYPEStimestamp_fmt_asc (Timestamp *, char *, int, char *);
|
||||
extern void PGTYPEStimestamp_current (Timestamp *);
|
||||
extern int PGTYPEStimestamp_defmt_asc(char *, char *, Timestamp *);
|
||||
extern int PGTYPEStimestamp_sub(Timestamp *, Timestamp *, Interval *);
|
||||
extern int PGTYPEStimestamp_fmt_asc(Timestamp *, char *, int, char *);
|
||||
extern void PGTYPEStimestamp_current(Timestamp *);
|
||||
extern int PGTYPEStimestamp_defmt_asc(char *, char *, Timestamp *);
|
||||
|
||||
#endif /* PGTYPES_TIMESTAMP */
|
||||
#endif /* PGTYPES_TIMESTAMP */
|
||||
|
@@ -56,7 +56,7 @@ struct sqlca_t
|
||||
struct sqlca_t *ECPGget_sqlca(void);
|
||||
|
||||
#ifndef POSTGRES_ECPG_INTERNAL
|
||||
# define sqlca (*ECPGget_sqlca())
|
||||
#define sqlca (*ECPGget_sqlca())
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -0,0 +1 @@
|
||||
|
||||
|
@@ -3,23 +3,23 @@
|
||||
#define CINTTYPE ECPGt_int
|
||||
#define CLONGTYPE ECPGt_long
|
||||
#define CFLOATTYPE ECPGt_float
|
||||
#define CDOUBLETYPE ECPGt_double
|
||||
#define CDOUBLETYPE ECPGt_double
|
||||
#define CDECIMALTYPE ECPGt_decimal
|
||||
#define CFIXCHARTYPE 108
|
||||
#define CSTRINGTYPE ECPGt_char
|
||||
#define CSTRINGTYPE ECPGt_char
|
||||
#define CDATETYPE ECPGt_date
|
||||
#define CMONEYTYPE 111
|
||||
#define CDTIMETYPE 112
|
||||
#define CLOCATORTYPE 113
|
||||
#define CVCHARTYPE ECPGt_varchar
|
||||
#define CLOCATORTYPE 113
|
||||
#define CVCHARTYPE ECPGt_varchar
|
||||
#define CINVTYPE 115
|
||||
#define CFILETYPE 116
|
||||
#define CINT8TYPE ECPGt_long_long
|
||||
#define CCOLLTYPE 118
|
||||
#define CLVCHARTYPE 119
|
||||
#define CFIXBINTYPE 120
|
||||
#define CVARBINTYPE 121
|
||||
#define CBOOLTYPE ECPGt_bool
|
||||
#define CROWTYPE 123
|
||||
#define CLVCHARPTRTYPE 124
|
||||
#define CCOLLTYPE 118
|
||||
#define CLVCHARTYPE 119
|
||||
#define CFIXBINTYPE 120
|
||||
#define CVARBINTYPE 121
|
||||
#define CBOOLTYPE ECPGt_bool
|
||||
#define CROWTYPE 123
|
||||
#define CLVCHARPTRTYPE 124
|
||||
#define CTYPEMAX 25
|
||||
|
@@ -5,7 +5,7 @@
|
||||
char *
|
||||
pgtypes_alloc(long size)
|
||||
{
|
||||
char *new = (char *) calloc(1L, size);
|
||||
char *new = (char *) calloc(1L, size);
|
||||
|
||||
if (!new)
|
||||
{
|
||||
@@ -20,7 +20,7 @@ pgtypes_alloc(long size)
|
||||
char *
|
||||
pgtypes_strdup(char *str)
|
||||
{
|
||||
char *new = (char *) strdup(str);
|
||||
char *new = (char *) strdup(str);
|
||||
|
||||
if (!new)
|
||||
errno = ENOMEM;
|
||||
@@ -28,40 +28,47 @@ pgtypes_strdup(char *str)
|
||||
}
|
||||
|
||||
int
|
||||
pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char** output, int *pstr_len) {
|
||||
/* general purpose variable, set to 0 in order to fix compiler
|
||||
* warning */
|
||||
int i = 0;
|
||||
switch(replace_type) {
|
||||
pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char **output, int *pstr_len)
|
||||
{
|
||||
/*
|
||||
* general purpose variable, set to 0 in order to fix compiler warning
|
||||
*/
|
||||
int i = 0;
|
||||
|
||||
switch (replace_type)
|
||||
{
|
||||
case PGTYPES_TYPE_NOTHING:
|
||||
break;
|
||||
case PGTYPES_TYPE_STRING_CONSTANT:
|
||||
case PGTYPES_TYPE_STRING_MALLOCED:
|
||||
i = strlen(replace_val.str_val);
|
||||
if (i + 1 <= *pstr_len) {
|
||||
/* copy over i + 1 bytes, that includes the
|
||||
* tailing terminator */
|
||||
if (i + 1 <= *pstr_len)
|
||||
{
|
||||
/*
|
||||
* copy over i + 1 bytes, that includes the tailing
|
||||
* terminator
|
||||
*/
|
||||
strncpy(*output, replace_val.str_val, i + 1);
|
||||
*pstr_len -= i;
|
||||
*output += i;
|
||||
if (replace_type == PGTYPES_TYPE_STRING_MALLOCED) {
|
||||
if (replace_type == PGTYPES_TYPE_STRING_MALLOCED)
|
||||
free(replace_val.str_val);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case PGTYPES_TYPE_CHAR:
|
||||
if (*pstr_len >= 2) {
|
||||
if (*pstr_len >= 2)
|
||||
{
|
||||
(*output)[0] = replace_val.char_val;
|
||||
(*output)[1] = '\0';
|
||||
(*pstr_len)--;
|
||||
(*output)++;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case PGTYPES_TYPE_DOUBLE_NF:
|
||||
case PGTYPES_TYPE_INT64:
|
||||
@@ -71,53 +78,58 @@ pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char** outp
|
||||
case PGTYPES_TYPE_UINT_3_LZ:
|
||||
case PGTYPES_TYPE_UINT_4_LZ:
|
||||
{
|
||||
char* t = pgtypes_alloc(PGTYPES_FMT_NUM_MAX_DIGITS);
|
||||
if (!t) {
|
||||
char *t = pgtypes_alloc(PGTYPES_FMT_NUM_MAX_DIGITS);
|
||||
|
||||
if (!t)
|
||||
return ENOMEM;
|
||||
}
|
||||
switch (replace_type) {
|
||||
switch (replace_type)
|
||||
{
|
||||
case PGTYPES_TYPE_DOUBLE_NF:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%0.0g", replace_val.double_val);
|
||||
"%0.0g", replace_val.double_val);
|
||||
break;
|
||||
#ifdef HAVE_INT64
|
||||
case PGTYPES_TYPE_INT64:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
INT64_FORMAT, replace_val.int64_val);
|
||||
INT64_FORMAT, replace_val.int64_val);
|
||||
break;
|
||||
#endif
|
||||
case PGTYPES_TYPE_UINT:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%u", replace_val.uint_val);
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%u", replace_val.uint_val);
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_2_LZ:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%02u", replace_val.uint_val);
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%02u", replace_val.uint_val);
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_2_LS:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%2u", replace_val.uint_val);
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%2u", replace_val.uint_val);
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_3_LZ:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%03u", replace_val.uint_val);
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%03u", replace_val.uint_val);
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_4_LZ:
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%04u", replace_val.uint_val);
|
||||
i = snprintf(t, PGTYPES_FMT_NUM_MAX_DIGITS,
|
||||
"%04u", replace_val.uint_val);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
if (i < 0)
|
||||
{
|
||||
free(t);
|
||||
return -1;
|
||||
}
|
||||
i = strlen(t);
|
||||
*pstr_len -= i;
|
||||
/* if *pstr_len == 0, we don't have enough
|
||||
* space for the terminator and the
|
||||
* conversion fails */
|
||||
if (*pstr_len <= 0) {
|
||||
|
||||
/*
|
||||
* if *pstr_len == 0, we don't have enough space for the
|
||||
* terminator and the conversion fails
|
||||
*/
|
||||
if (*pstr_len <= 0)
|
||||
{
|
||||
free(t);
|
||||
return -1;
|
||||
}
|
||||
@@ -131,5 +143,3 @@ pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char** outp
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -14,17 +14,17 @@ PGTYPESdate_from_timestamp(Timestamp dt)
|
||||
{
|
||||
Date dDate;
|
||||
|
||||
dDate = 0; /* suppress compiler warning */
|
||||
dDate = 0; /* suppress compiler warning */
|
||||
|
||||
if (TIMESTAMP_NOT_FINITE(dt))
|
||||
return
|
||||
return
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
/* Microseconds to days */
|
||||
dDate = (dt / INT64CONST(86400000000));
|
||||
/* Microseconds to days */
|
||||
dDate = (dt / INT64CONST(86400000000));
|
||||
#else
|
||||
/* Seconds to days */
|
||||
dDate = (dt / 86400.0);
|
||||
/* Seconds to days */
|
||||
dDate = (dt / 86400.0);
|
||||
#endif
|
||||
|
||||
return dDate;
|
||||
@@ -33,7 +33,7 @@ PGTYPESdate_from_timestamp(Timestamp dt)
|
||||
Date
|
||||
PGTYPESdate_from_asc(char *str, char **endptr)
|
||||
{
|
||||
|
||||
|
||||
Date dDate;
|
||||
fsec_t fsec;
|
||||
struct tm tt,
|
||||
@@ -44,9 +44,9 @@ PGTYPESdate_from_asc(char *str, char **endptr)
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN + 1];
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
bool EuroDates = FALSE;
|
||||
|
||||
errno = 0;
|
||||
@@ -57,7 +57,7 @@ PGTYPESdate_from_asc(char *str, char **endptr)
|
||||
}
|
||||
|
||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, EuroDates) != 0))
|
||||
{
|
||||
errno = PGTYPES_DATE_BAD_DATE;
|
||||
return 0;
|
||||
@@ -69,7 +69,7 @@ PGTYPESdate_from_asc(char *str, char **endptr)
|
||||
break;
|
||||
|
||||
case DTK_EPOCH:
|
||||
GetEpochTime(tm);
|
||||
GetEpochTime(tm);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -85,21 +85,24 @@ PGTYPESdate_from_asc(char *str, char **endptr)
|
||||
char *
|
||||
PGTYPESdate_to_asc(Date dDate)
|
||||
{
|
||||
struct tm tt, *tm = &tt;
|
||||
char buf[MAXDATELEN + 1];
|
||||
int DateStyle=1;
|
||||
struct tm tt,
|
||||
*tm = &tt;
|
||||
char buf[MAXDATELEN + 1];
|
||||
int DateStyle = 1;
|
||||
bool EuroDates = FALSE;
|
||||
|
||||
|
||||
j2date((dDate + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
|
||||
EncodeDateOnly(tm, DateStyle, buf, EuroDates);
|
||||
return pgtypes_strdup(buf);
|
||||
}
|
||||
|
||||
void
|
||||
PGTYPESdate_julmdy(Date jd, int* mdy)
|
||||
PGTYPESdate_julmdy(Date jd, int *mdy)
|
||||
{
|
||||
int y, m, d;
|
||||
|
||||
int y,
|
||||
m,
|
||||
d;
|
||||
|
||||
j2date((int) (jd + date2j(2000, 1, 1)), &y, &m, &d);
|
||||
mdy[0] = m;
|
||||
mdy[1] = d;
|
||||
@@ -107,10 +110,10 @@ PGTYPESdate_julmdy(Date jd, int* mdy)
|
||||
}
|
||||
|
||||
void
|
||||
PGTYPESdate_mdyjul(int* mdy, Date *jdate)
|
||||
PGTYPESdate_mdyjul(int *mdy, Date * jdate)
|
||||
{
|
||||
/* month is mdy[0] */
|
||||
/* day is mdy[1] */
|
||||
/* day is mdy[1] */
|
||||
/* year is mdy[2] */
|
||||
|
||||
*jdate = (Date) (date2j(mdy[2], mdy[0], mdy[1]) - date2j(2000, 1, 1));
|
||||
@@ -120,19 +123,14 @@ int
|
||||
PGTYPESdate_dayofweek(Date dDate)
|
||||
{
|
||||
/*
|
||||
Sunday: 0
|
||||
Monday: 1
|
||||
Tuesday: 2
|
||||
Wednesday: 3
|
||||
Thursday: 4
|
||||
Friday: 5
|
||||
Saturday: 6
|
||||
*/
|
||||
return 6-j2day(dDate+3);
|
||||
* Sunday: 0 Monday: 1 Tuesday: 2 Wednesday: 3
|
||||
* Thursday: 4 Friday: 5 Saturday: 6
|
||||
*/
|
||||
return 6 - j2day(dDate + 3);
|
||||
}
|
||||
|
||||
void
|
||||
PGTYPESdate_today (Date *d)
|
||||
PGTYPESdate_today(Date * d)
|
||||
{
|
||||
struct tm ts;
|
||||
|
||||
@@ -141,40 +139,60 @@ PGTYPESdate_today (Date *d)
|
||||
return;
|
||||
}
|
||||
|
||||
#define PGTYPES_DATE_NUM_MAX_DIGITS 20 /* should suffice for most years... */
|
||||
#define PGTYPES_DATE_NUM_MAX_DIGITS 20 /* should suffice for most
|
||||
* years... */
|
||||
|
||||
#define PGTYPES_FMTDATE_DAY_DIGITS_LZ 1 /* LZ means "leading zeroes" */
|
||||
#define PGTYPES_FMTDATE_DAY_DIGITS_LZ 1 /* LZ means "leading
|
||||
* zeroes" */
|
||||
#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT 2
|
||||
#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ 3
|
||||
#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT 4
|
||||
#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT 4
|
||||
#define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT 5
|
||||
#define PGTYPES_FMTDATE_YEAR_DIGITS_LONG 6
|
||||
|
||||
int
|
||||
PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) {
|
||||
static struct {
|
||||
char* format;
|
||||
int component;
|
||||
} mapping[] = {
|
||||
/* format items have to be sorted according to their length,
|
||||
* since the first pattern that matches gets replaced by its
|
||||
* value */
|
||||
{"ddd", PGTYPES_FMTDATE_DOW_LITERAL_SHORT },
|
||||
{"dd", PGTYPES_FMTDATE_DAY_DIGITS_LZ },
|
||||
{"mmm", PGTYPES_FMTDATE_MONTH_LITERAL_SHORT },
|
||||
{"mm", PGTYPES_FMTDATE_MONTH_DIGITS_LZ },
|
||||
{"yyyy", PGTYPES_FMTDATE_YEAR_DIGITS_LONG },
|
||||
{"yy", PGTYPES_FMTDATE_YEAR_DIGITS_SHORT },
|
||||
{ NULL, 0 }
|
||||
PGTYPESdate_fmt_asc(Date dDate, char *fmtstring, char *outbuf)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
char *format;
|
||||
int component;
|
||||
} mapping[] =
|
||||
{
|
||||
/*
|
||||
* format items have to be sorted according to their length, since
|
||||
* the first pattern that matches gets replaced by its value
|
||||
*/
|
||||
{
|
||||
"ddd", PGTYPES_FMTDATE_DOW_LITERAL_SHORT
|
||||
},
|
||||
{
|
||||
"dd", PGTYPES_FMTDATE_DAY_DIGITS_LZ
|
||||
},
|
||||
{
|
||||
"mmm", PGTYPES_FMTDATE_MONTH_LITERAL_SHORT
|
||||
},
|
||||
{
|
||||
"mm", PGTYPES_FMTDATE_MONTH_DIGITS_LZ
|
||||
},
|
||||
{
|
||||
"yyyy", PGTYPES_FMTDATE_YEAR_DIGITS_LONG
|
||||
},
|
||||
{
|
||||
"yy", PGTYPES_FMTDATE_YEAR_DIGITS_SHORT
|
||||
},
|
||||
{
|
||||
NULL, 0
|
||||
}
|
||||
};
|
||||
|
||||
union un_fmt_comb replace_val;
|
||||
int replace_type;
|
||||
int replace_type;
|
||||
|
||||
int i;
|
||||
int dow;
|
||||
char* start_pattern;
|
||||
struct tm tm;
|
||||
int i;
|
||||
int dow;
|
||||
char *start_pattern;
|
||||
struct tm tm;
|
||||
|
||||
/* XXX error handling ? */
|
||||
/* copy the string over */
|
||||
@@ -184,9 +202,12 @@ PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) {
|
||||
j2date((dDate + date2j(2000, 1, 1)), &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
|
||||
dow = PGTYPESdate_dayofweek(dDate);
|
||||
|
||||
for (i = 0; mapping[i].format != NULL; i++) {
|
||||
while ((start_pattern = strstr(outbuf, mapping[i].format)) != NULL) {
|
||||
switch(mapping[i].component) {
|
||||
for (i = 0; mapping[i].format != NULL; i++)
|
||||
{
|
||||
while ((start_pattern = strstr(outbuf, mapping[i].format)) != NULL)
|
||||
{
|
||||
switch (mapping[i].component)
|
||||
{
|
||||
case PGTYPES_FMTDATE_DOW_LITERAL_SHORT:
|
||||
replace_val.str_val = pgtypes_date_weekdays_short[dow];
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
@@ -196,7 +217,7 @@ PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) {
|
||||
replace_type = PGTYPES_TYPE_UINT_2_LZ;
|
||||
break;
|
||||
case PGTYPES_FMTDATE_MONTH_LITERAL_SHORT:
|
||||
replace_val.str_val = months[tm.tm_mon-1];
|
||||
replace_val.str_val = months[tm.tm_mon - 1];
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
break;
|
||||
case PGTYPES_FMTDATE_MONTH_DIGITS_LZ:
|
||||
@@ -212,61 +233,65 @@ PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) {
|
||||
replace_type = PGTYPES_TYPE_UINT_2_LZ;
|
||||
break;
|
||||
default:
|
||||
/* should not happen, set something
|
||||
* anyway */
|
||||
|
||||
/*
|
||||
* should not happen, set something anyway
|
||||
*/
|
||||
replace_val.str_val = " ";
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
}
|
||||
switch(replace_type) {
|
||||
switch (replace_type)
|
||||
{
|
||||
case PGTYPES_TYPE_STRING_MALLOCED:
|
||||
case PGTYPES_TYPE_STRING_CONSTANT:
|
||||
strncpy(start_pattern, replace_val.str_val,
|
||||
strlen(replace_val.str_val));
|
||||
if (replace_type == PGTYPES_TYPE_STRING_MALLOCED) {
|
||||
if (replace_type == PGTYPES_TYPE_STRING_MALLOCED)
|
||||
free(replace_val.str_val);
|
||||
}
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT:
|
||||
{
|
||||
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
if (!t) {
|
||||
char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
|
||||
if (!t)
|
||||
return -1;
|
||||
}
|
||||
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||
"%u", replace_val.uint_val);
|
||||
"%u", replace_val.uint_val);
|
||||
strncpy(start_pattern, t, strlen(t));
|
||||
free(t);
|
||||
}
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_2_LZ:
|
||||
{
|
||||
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
if (!t) {
|
||||
char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
|
||||
if (!t)
|
||||
return -1;
|
||||
}
|
||||
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||
"%02u", replace_val.uint_val);
|
||||
"%02u", replace_val.uint_val);
|
||||
strncpy(start_pattern, t, strlen(t));
|
||||
free(t);
|
||||
}
|
||||
break;
|
||||
case PGTYPES_TYPE_UINT_4_LZ:
|
||||
{
|
||||
char* t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
if (!t) {
|
||||
char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS);
|
||||
|
||||
if (!t)
|
||||
return -1;
|
||||
}
|
||||
snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS,
|
||||
"%04u", replace_val.uint_val);
|
||||
"%04u", replace_val.uint_val);
|
||||
strncpy(start_pattern, t, strlen(t));
|
||||
free(t);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* doesn't happen (we set
|
||||
* replace_type to
|
||||
* PGTYPES_TYPE_STRING_CONSTANT
|
||||
* in case of an error above) */
|
||||
|
||||
/*
|
||||
* doesn't happen (we set replace_type to
|
||||
* PGTYPES_TYPE_STRING_CONSTANT in case of an error
|
||||
* above)
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -279,32 +304,37 @@ PGTYPESdate_fmt_asc(Date dDate, char* fmtstring, char* outbuf) {
|
||||
* PGTYPESdate_defmt_asc
|
||||
*
|
||||
* function works as follows:
|
||||
* - first we analyze the paramters
|
||||
* - if this is a special case with no delimiters, add delimters
|
||||
* - find the tokens. First we look for numerical values. If we have found
|
||||
* less than 3 tokens, we check for the months' names and thereafter for
|
||||
* the abbreviations of the months' names.
|
||||
* - then we see which parameter should be the date, the month and the
|
||||
* year and from these values we calculate the date
|
||||
* - first we analyze the paramters
|
||||
* - if this is a special case with no delimiters, add delimters
|
||||
* - find the tokens. First we look for numerical values. If we have found
|
||||
* less than 3 tokens, we check for the months' names and thereafter for
|
||||
* the abbreviations of the months' names.
|
||||
* - then we see which parameter should be the date, the month and the
|
||||
* year and from these values we calculate the date
|
||||
*/
|
||||
|
||||
#define PGTYPES_DATE_MONTH_MAXLENGTH 20 /* probably even less :-) */
|
||||
#define PGTYPES_DATE_MONTH_MAXLENGTH 20 /* probably even less :-) */
|
||||
int
|
||||
PGTYPESdate_defmt_asc(Date *d, char *fmt, char *str)
|
||||
PGTYPESdate_defmt_asc(Date * d, char *fmt, char *str)
|
||||
{
|
||||
/* token[2] = { 4,6 } means that token 2 starts at
|
||||
* position 4 and ends at (including) position 6 */
|
||||
int token[3][2];
|
||||
int token_values[3] = { -1, -1, -1 };
|
||||
char* fmt_token_order;
|
||||
char* fmt_ystart, *fmt_mstart, *fmt_dstart;
|
||||
int i;
|
||||
int reading_digit;
|
||||
int token_count;
|
||||
char* str_copy;
|
||||
struct tm tm;
|
||||
/*
|
||||
* token[2] = { 4,6 } means that token 2 starts at position 4 and ends
|
||||
* at (including) position 6
|
||||
*/
|
||||
int token[3][2];
|
||||
int token_values[3] = {-1, -1, -1};
|
||||
char *fmt_token_order;
|
||||
char *fmt_ystart,
|
||||
*fmt_mstart,
|
||||
*fmt_dstart;
|
||||
int i;
|
||||
int reading_digit;
|
||||
int token_count;
|
||||
char *str_copy;
|
||||
struct tm tm;
|
||||
|
||||
if (!d || !str || !fmt) {
|
||||
if (!d || !str || !fmt)
|
||||
{
|
||||
errno = PGTYPES_DATE_ERR_EARGS;
|
||||
return -1;
|
||||
}
|
||||
@@ -314,229 +344,305 @@ PGTYPESdate_defmt_asc(Date *d, char *fmt, char *str)
|
||||
fmt_mstart = strstr(fmt, "mm");
|
||||
fmt_dstart = strstr(fmt, "dd");
|
||||
|
||||
if (!fmt_ystart || !fmt_mstart || !fmt_dstart) {
|
||||
if (!fmt_ystart || !fmt_mstart || !fmt_dstart)
|
||||
{
|
||||
errno = PGTYPES_DATE_ERR_EARGS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fmt_ystart < fmt_mstart) {
|
||||
if (fmt_ystart < fmt_mstart)
|
||||
{
|
||||
/* y m */
|
||||
if (fmt_dstart < fmt_ystart) {
|
||||
if (fmt_dstart < fmt_ystart)
|
||||
{
|
||||
/* d y m */
|
||||
fmt_token_order = "dym";
|
||||
} else if (fmt_dstart > fmt_mstart) {
|
||||
}
|
||||
else if (fmt_dstart > fmt_mstart)
|
||||
{
|
||||
/* y m d */
|
||||
fmt_token_order = "ymd";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* y d m */
|
||||
fmt_token_order = "ydm";
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fmt_ystart > fmt_mstart */
|
||||
/* m y */
|
||||
if (fmt_dstart < fmt_mstart) {
|
||||
if (fmt_dstart < fmt_mstart)
|
||||
{
|
||||
/* d m y */
|
||||
fmt_token_order = "dmy";
|
||||
} else if (fmt_dstart > fmt_ystart) {
|
||||
}
|
||||
else if (fmt_dstart > fmt_ystart)
|
||||
{
|
||||
/* m y d */
|
||||
fmt_token_order = "myd";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* m d y */
|
||||
fmt_token_order = "mdy";
|
||||
}
|
||||
}
|
||||
|
||||
/* handle the special cases where there is no delimiter between the
|
||||
/*
|
||||
* handle the special cases where there is no delimiter between the
|
||||
* digits. If we see this:
|
||||
*
|
||||
* only digits, 6 or 8 bytes then it might be ddmmyy and ddmmyyyy
|
||||
* (or similar)
|
||||
* only digits, 6 or 8 bytes then it might be ddmmyy and ddmmyyyy (or
|
||||
* similar)
|
||||
*
|
||||
* we reduce it to a string with delimiters and continue processing
|
||||
* */
|
||||
*/
|
||||
|
||||
/* check if we have only digits */
|
||||
reading_digit = 1;
|
||||
for (i = 0; str[i]; i++) {
|
||||
if (!isdigit(str[i])) {
|
||||
for (i = 0; str[i]; i++)
|
||||
{
|
||||
if (!isdigit(str[i]))
|
||||
{
|
||||
reading_digit = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (reading_digit) {
|
||||
int frag_length[3];
|
||||
int target_pos;
|
||||
if (reading_digit)
|
||||
{
|
||||
int frag_length[3];
|
||||
int target_pos;
|
||||
|
||||
i = strlen(str);
|
||||
if (i != 8 && i != 6) {
|
||||
if (i != 8 && i != 6)
|
||||
{
|
||||
errno = PGTYPES_DATE_ERR_ENOSHORTDATE;
|
||||
return -1;
|
||||
}
|
||||
/* okay, this really is the special case */
|
||||
|
||||
/* as long as the string, one additional byte for the
|
||||
* terminator and 2 for the delimiters between the 3 fiedls
|
||||
* */
|
||||
/*
|
||||
* as long as the string, one additional byte for the terminator
|
||||
* and 2 for the delimiters between the 3 fiedls
|
||||
*/
|
||||
str_copy = pgtypes_alloc(strlen(str) + 1 + 2);
|
||||
if (!str_copy) {
|
||||
if (!str_copy)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* determine length of the fragments */
|
||||
if (i == 6) {
|
||||
frag_length[0] = 2; frag_length[1] = 2; frag_length[2] = 2;
|
||||
} else {
|
||||
if (fmt_token_order[0] == 'y') {
|
||||
frag_length[0] = 4; frag_length[1] = 2; frag_length[2] = 2;
|
||||
} else if (fmt_token_order[1] == 'y') {
|
||||
frag_length[0] = 2; frag_length[1] = 4; frag_length[2] = 2;
|
||||
} else {
|
||||
frag_length[0] = 2; frag_length[1] = 2; frag_length[2] = 4;
|
||||
if (i == 6)
|
||||
{
|
||||
frag_length[0] = 2;
|
||||
frag_length[1] = 2;
|
||||
frag_length[2] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fmt_token_order[0] == 'y')
|
||||
{
|
||||
frag_length[0] = 4;
|
||||
frag_length[1] = 2;
|
||||
frag_length[2] = 2;
|
||||
}
|
||||
else if (fmt_token_order[1] == 'y')
|
||||
{
|
||||
frag_length[0] = 2;
|
||||
frag_length[1] = 4;
|
||||
frag_length[2] = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
frag_length[0] = 2;
|
||||
frag_length[1] = 2;
|
||||
frag_length[2] = 4;
|
||||
}
|
||||
}
|
||||
target_pos = 0;
|
||||
/* XXX: Here we could calculate the positions of the tokens
|
||||
* and save the for loop down there where we again check
|
||||
* with isdigit() for digits. */
|
||||
for (i = 0; i < 3; i++) {
|
||||
int start_pos = 0;
|
||||
if (i >= 1) { start_pos += frag_length[0]; }
|
||||
if (i == 2) { start_pos += frag_length[1]; }
|
||||
|
||||
/*
|
||||
* XXX: Here we could calculate the positions of the tokens and
|
||||
* save the for loop down there where we again check with
|
||||
* isdigit() for digits.
|
||||
*/
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
int start_pos = 0;
|
||||
|
||||
if (i >= 1)
|
||||
start_pos += frag_length[0];
|
||||
if (i == 2)
|
||||
start_pos += frag_length[1];
|
||||
|
||||
strncpy(str_copy + target_pos, str + start_pos,
|
||||
frag_length[i]);
|
||||
frag_length[i]);
|
||||
target_pos += frag_length[i];
|
||||
if (i != 2) {
|
||||
if (i != 2)
|
||||
{
|
||||
str_copy[target_pos] = ' ';
|
||||
target_pos++;
|
||||
}
|
||||
}
|
||||
str_copy[target_pos] = '\0';
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
str_copy = pgtypes_strdup(str);
|
||||
if (!str_copy) {
|
||||
if (!str_copy)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert the whole string to lower case */
|
||||
for (i = 0; str_copy[i]; i++) {
|
||||
for (i = 0; str_copy[i]; i++)
|
||||
str_copy[i] = (char) tolower(str_copy[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* look for numerical tokens */
|
||||
reading_digit = 0;
|
||||
token_count = 0;
|
||||
for (i = 0; i < strlen(str_copy); i++) {
|
||||
if (!isdigit(str_copy[i]) && reading_digit) {
|
||||
token_count = 0;
|
||||
for (i = 0; i < strlen(str_copy); i++)
|
||||
{
|
||||
if (!isdigit(str_copy[i]) && reading_digit)
|
||||
{
|
||||
/* the token is finished */
|
||||
token[token_count][1] = i-1;
|
||||
token[token_count][1] = i - 1;
|
||||
reading_digit = 0;
|
||||
token_count++;
|
||||
} else if (isdigit(str_copy[i]) && !reading_digit) {
|
||||
}
|
||||
else if (isdigit(str_copy[i]) && !reading_digit)
|
||||
{
|
||||
/* we have found a token */
|
||||
token[token_count][0] = i;
|
||||
reading_digit = 1;
|
||||
}
|
||||
}
|
||||
/* we're at the end of the input string, but maybe we are still reading a
|
||||
* number... */
|
||||
if (reading_digit) {
|
||||
token[token_count][1] = i-1;
|
||||
|
||||
/*
|
||||
* we're at the end of the input string, but maybe we are still
|
||||
* reading a number...
|
||||
*/
|
||||
if (reading_digit)
|
||||
{
|
||||
token[token_count][1] = i - 1;
|
||||
token_count++;
|
||||
}
|
||||
|
||||
|
||||
if (token_count < 2) {
|
||||
/* not all tokens found, no way to find 2 missing tokens
|
||||
* with string matches */
|
||||
if (token_count < 2)
|
||||
{
|
||||
/*
|
||||
* not all tokens found, no way to find 2 missing tokens with
|
||||
* string matches
|
||||
*/
|
||||
free(str_copy);
|
||||
errno = PGTYPES_DATE_ERR_ENOTDMY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (token_count != 3) {
|
||||
/* not all tokens found but we may find another one with
|
||||
* string matches by testing for the months names and months
|
||||
* abbreviations */
|
||||
char *month_lower_tmp = pgtypes_alloc(PGTYPES_DATE_MONTH_MAXLENGTH);
|
||||
char *start_pos;
|
||||
int j;
|
||||
int offset;
|
||||
int found = 0;
|
||||
char** list;
|
||||
if (token_count != 3)
|
||||
{
|
||||
/*
|
||||
* not all tokens found but we may find another one with string
|
||||
* matches by testing for the months names and months
|
||||
* abbreviations
|
||||
*/
|
||||
char *month_lower_tmp = pgtypes_alloc(PGTYPES_DATE_MONTH_MAXLENGTH);
|
||||
char *start_pos;
|
||||
int j;
|
||||
int offset;
|
||||
int found = 0;
|
||||
char **list;
|
||||
|
||||
if (!month_lower_tmp) {
|
||||
if (!month_lower_tmp)
|
||||
{
|
||||
/* free variables we alloc'ed before */
|
||||
free(str_copy);
|
||||
return -1;
|
||||
}
|
||||
list = pgtypes_date_months;
|
||||
for (i = 0; list[i]; i++) {
|
||||
for (j = 0; j < PGTYPES_DATE_MONTH_MAXLENGTH; j++) {
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
for (j = 0; j < PGTYPES_DATE_MONTH_MAXLENGTH; j++)
|
||||
{
|
||||
month_lower_tmp[j] = (char) tolower(list[i][j]);
|
||||
if (!month_lower_tmp[j]) {
|
||||
if (!month_lower_tmp[j])
|
||||
{
|
||||
/* properly terminated */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((start_pos = strstr(str_copy, month_lower_tmp))) {
|
||||
if ((start_pos = strstr(str_copy, month_lower_tmp)))
|
||||
{
|
||||
offset = start_pos - str_copy;
|
||||
/* sort the new token into the numeric
|
||||
* tokens, shift them if necessary */
|
||||
if (offset < token[0][0]) {
|
||||
|
||||
/*
|
||||
* sort the new token into the numeric tokens, shift them
|
||||
* if necessary
|
||||
*/
|
||||
if (offset < token[0][0])
|
||||
{
|
||||
token[2][0] = token[1][0];
|
||||
token[2][1] = token[1][1];
|
||||
token[1][0] = token[0][0];
|
||||
token[1][1] = token[0][1];
|
||||
token_count = 0;
|
||||
} else if (offset < token[1][0]) {
|
||||
}
|
||||
else if (offset < token[1][0])
|
||||
{
|
||||
token[2][0] = token[1][0];
|
||||
token[2][1] = token[1][1];
|
||||
token_count = 1;
|
||||
} else {
|
||||
token_count = 2;
|
||||
}
|
||||
else
|
||||
token_count = 2;
|
||||
token[token_count][0] = offset;
|
||||
token[token_count][1] = offset + strlen(month_lower_tmp) - 1;
|
||||
/* the value is the index of the month in
|
||||
* the array of months + 1 (January is month
|
||||
* 0) */
|
||||
token_values[token_count] = i+1;
|
||||
|
||||
/*
|
||||
* the value is the index of the month in the array of
|
||||
* months + 1 (January is month 0)
|
||||
*/
|
||||
token_values[token_count] = i + 1;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
/* evil[tm] hack:
|
||||
* if we read the pgtypes_date_months and haven't
|
||||
* found a match, reset list to point to
|
||||
* pgtypes_date_months_short and reset the counter
|
||||
* variable i */
|
||||
if (list == pgtypes_date_months) {
|
||||
if (list[i+1] == NULL) {
|
||||
|
||||
/*
|
||||
* evil[tm] hack: if we read the pgtypes_date_months and
|
||||
* haven't found a match, reset list to point to
|
||||
* pgtypes_date_months_short and reset the counter variable i
|
||||
*/
|
||||
if (list == pgtypes_date_months)
|
||||
{
|
||||
if (list[i + 1] == NULL)
|
||||
{
|
||||
list = months;
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (!found)
|
||||
{
|
||||
free(month_lower_tmp);
|
||||
free(str_copy);
|
||||
errno = PGTYPES_DATE_ERR_ENOTDMY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* here we found a month. token[token_count] and
|
||||
/*
|
||||
* here we found a month. token[token_count] and
|
||||
* token_values[token_count] reflect the month's details.
|
||||
*
|
||||
* only the month can be specified with a literal. Here we can do a
|
||||
* quick check if the month is at the right position according to
|
||||
* the format string because we can check if the token that
|
||||
* we expect to be the month is at the position of the only
|
||||
* token that already has a value. If we wouldn't check here
|
||||
* we could say "December 4 1990" with a fmt string of
|
||||
* "dd mm yy" for 12 April 1990.
|
||||
* the format string because we can check if the token that we
|
||||
* expect to be the month is at the position of the only token
|
||||
* that already has a value. If we wouldn't check here we could
|
||||
* say "December 4 1990" with a fmt string of "dd mm yy" for 12
|
||||
* April 1990.
|
||||
*/
|
||||
if (fmt_token_order[token_count] != 'm') {
|
||||
if (fmt_token_order[token_count] != 'm')
|
||||
{
|
||||
/* deal with the error later on */
|
||||
token_values[token_count] = -1;
|
||||
}
|
||||
@@ -544,24 +650,24 @@ PGTYPESdate_defmt_asc(Date *d, char *fmt, char *str)
|
||||
}
|
||||
|
||||
/* terminate the tokens with ASCII-0 and get their values */
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
*(str_copy + token[i][1] + 1) = '\0';
|
||||
/* A month already has a value set, check for token_value == -1 */
|
||||
if (token_values[i] == -1) {
|
||||
if (token_values[i] == -1)
|
||||
{
|
||||
errno = 0;
|
||||
token_values[i] = strtol(str_copy + token[i][0], (char **) NULL, 10);
|
||||
/* strtol sets errno in case of an error */
|
||||
if (errno) {
|
||||
if (errno)
|
||||
token_values[i] = -1;
|
||||
}
|
||||
}
|
||||
if (fmt_token_order[i] == 'd') {
|
||||
if (fmt_token_order[i] == 'd')
|
||||
tm.tm_mday = token_values[i];
|
||||
} else if (fmt_token_order[i] == 'm') {
|
||||
else if (fmt_token_order[i] == 'm')
|
||||
tm.tm_mon = token_values[i];
|
||||
} else if (fmt_token_order[i] == 'y') {
|
||||
else if (fmt_token_order[i] == 'y')
|
||||
tm.tm_year = token_values[i];
|
||||
}
|
||||
}
|
||||
free(str_copy);
|
||||
|
||||
@@ -577,7 +683,7 @@ PGTYPESdate_defmt_asc(Date *d, char *fmt, char *str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tm.tm_mday == 31 && (tm.tm_mon == 4 || tm.tm_mon == 6 || tm.tm_mon == 9 || tm.tm_mon ==11))
|
||||
if (tm.tm_mday == 31 && (tm.tm_mon == 4 || tm.tm_mon == 6 || tm.tm_mon == 9 || tm.tm_mon == 11))
|
||||
{
|
||||
errno = PGTYPES_DATE_BAD_DAY;
|
||||
return -1;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <pgtypes_timestamp.h>
|
||||
|
||||
#define MAXTZLEN 10
|
||||
#define MAXTZLEN 10
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
|
||||
@@ -17,10 +17,10 @@ typedef double fsec_t;
|
||||
#define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
|
||||
#endif
|
||||
|
||||
#define USE_POSTGRES_DATES 0
|
||||
#define USE_ISO_DATES 1
|
||||
#define USE_SQL_DATES 2
|
||||
#define USE_GERMAN_DATES 3
|
||||
#define USE_POSTGRES_DATES 0
|
||||
#define USE_ISO_DATES 1
|
||||
#define USE_SQL_DATES 2
|
||||
#define USE_GERMAN_DATES 3
|
||||
|
||||
#define DAGO "ago"
|
||||
#define EPOCH "epoch"
|
||||
@@ -49,7 +49,7 @@ typedef double fsec_t;
|
||||
#define DA_D "ad"
|
||||
#define DB_C "bc"
|
||||
#define DTIMEZONE "timezone"
|
||||
#define DCURRENT "current"
|
||||
#define DCURRENT "current"
|
||||
|
||||
/*
|
||||
* Fundamental time field definitions for parsing.
|
||||
@@ -275,13 +275,12 @@ do { \
|
||||
#define DT_NOBEGIN (-DBL_MAX)
|
||||
#define DT_NOEND (DBL_MAX)
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_INT64_TIMESTAMP */
|
||||
|
||||
#define TIMESTAMP_NOBEGIN(j) do {j = DT_NOBEGIN;} while (0)
|
||||
#define TIMESTAMP_NOEND(j) do {j = DT_NOEND;} while (0)
|
||||
#define TIMESTAMP_NOBEGIN(j) do {j = DT_NOBEGIN;} while (0)
|
||||
#define TIMESTAMP_NOEND(j) do {j = DT_NOEND;} while (0)
|
||||
#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
|
||||
#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
|
||||
#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
|
||||
#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
|
||||
|
||||
int DecodeTimeOnly(char **field, int *ftype,
|
||||
@@ -292,31 +291,30 @@ int DecodeInterval(char **field, int *ftype,
|
||||
int nf, int *dtype,
|
||||
struct tm * tm, fsec_t *fsec);
|
||||
|
||||
int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str);
|
||||
int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool);
|
||||
int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str);
|
||||
int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str);
|
||||
int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool);
|
||||
int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str);
|
||||
|
||||
int tm2timestamp(struct tm *, fsec_t, int *, Timestamp *);
|
||||
int tm2timestamp(struct tm *, fsec_t, int *, Timestamp *);
|
||||
|
||||
int DecodeUnits(int field, char *lowtoken, int *val);
|
||||
bool ClearDateCache(bool, bool, bool);
|
||||
int DecodeUnits(int field, char *lowtoken, int *val);
|
||||
bool ClearDateCache(bool, bool, bool);
|
||||
|
||||
int j2day(int jd);
|
||||
int j2day(int jd);
|
||||
|
||||
bool CheckDateTokenTables(void);
|
||||
bool CheckDateTokenTables(void);
|
||||
|
||||
int EncodeDateOnly(struct tm *, int, char *, bool);
|
||||
void GetEpochTime(struct tm *);
|
||||
int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
|
||||
int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
|
||||
void j2date(int, int *, int *, int *);
|
||||
void GetCurrentDateTime(struct tm*);
|
||||
int date2j(int, int, int);
|
||||
int EncodeDateOnly(struct tm *, int, char *, bool);
|
||||
void GetEpochTime(struct tm *);
|
||||
int ParseDateTime(char *, char *, char **, int *, int, int *, char **);
|
||||
int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, int *, bool);
|
||||
void j2date(int, int *, int *, int *);
|
||||
void GetCurrentDateTime(struct tm *);
|
||||
int date2j(int, int, int);
|
||||
|
||||
extern char* pgtypes_date_weekdays_short[];
|
||||
extern char* pgtypes_date_months[];
|
||||
extern char* months[];
|
||||
extern char* days[];
|
||||
extern char *pgtypes_date_weekdays_short[];
|
||||
extern char *pgtypes_date_months[];
|
||||
extern char *months[];
|
||||
extern char *days[];
|
||||
|
||||
#endif /* DT_H */
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -9,44 +9,46 @@
|
||||
#define PGTYPES_TYPE_STRING_MALLOCED 1
|
||||
#define PGTYPES_TYPE_STRING_CONSTANT 2
|
||||
#define PGTYPES_TYPE_CHAR 3
|
||||
#define PGTYPES_TYPE_DOUBLE_NF 4 /* no fractional part */
|
||||
#define PGTYPES_TYPE_DOUBLE_NF 4 /* no fractional part */
|
||||
#define PGTYPES_TYPE_INT64 5
|
||||
#define PGTYPES_TYPE_UINT 6
|
||||
#define PGTYPES_TYPE_UINT_2_LZ 7 /* 2 digits, pad with leading zero */
|
||||
#define PGTYPES_TYPE_UINT_2_LS 8 /* 2 digits, pad with leading space */
|
||||
#define PGTYPES_TYPE_UINT_2_LZ 7 /* 2 digits, pad with
|
||||
* leading zero */
|
||||
#define PGTYPES_TYPE_UINT_2_LS 8 /* 2 digits, pad with
|
||||
* leading space */
|
||||
#define PGTYPES_TYPE_UINT_3_LZ 9
|
||||
#define PGTYPES_TYPE_UINT_4_LZ 10
|
||||
#define PGTYPES_TYPE_UINT_LONG 11
|
||||
|
||||
#define PGTYPES_FMT_NUM_MAX_DIGITS 40
|
||||
|
||||
union un_fmt_comb {
|
||||
char* str_val;
|
||||
unsigned int uint_val;
|
||||
char char_val;
|
||||
unsigned long int luint_val;
|
||||
double double_val;
|
||||
union un_fmt_comb
|
||||
{
|
||||
char *str_val;
|
||||
unsigned int uint_val;
|
||||
char char_val;
|
||||
unsigned long int luint_val;
|
||||
double double_val;
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 int64_val;
|
||||
int64 int64_val;
|
||||
#endif
|
||||
};
|
||||
|
||||
int pgtypes_fmt_replace(union un_fmt_comb, int, char**, int*);
|
||||
int pgtypes_fmt_replace(union un_fmt_comb, int, char **, int *);
|
||||
|
||||
char *pgtypes_alloc(long);
|
||||
char *pgtypes_strdup(char *);
|
||||
char *pgtypes_alloc(long);
|
||||
char *pgtypes_strdup(char *);
|
||||
|
||||
#ifndef bool
|
||||
#define bool char
|
||||
#endif /* ndef bool */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#define FALSE 0
|
||||
#endif /* FALSE */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif /* TRUE */
|
||||
|
||||
#endif /* __PGTYPES_COMMON_H__ */
|
||||
#define TRUE 1
|
||||
#endif /* TRUE */
|
||||
|
||||
#endif /* __PGTYPES_COMMON_H__ */
|
||||
|
@@ -743,7 +743,7 @@ tm2interval(struct tm * tm, fsec_t fsec, Interval *span)
|
||||
Interval *
|
||||
PGTYPESinterval_from_asc(char *str, char **endptr)
|
||||
{
|
||||
Interval *result = NULL;
|
||||
Interval *result = NULL;
|
||||
fsec_t fsec;
|
||||
struct tm tt,
|
||||
*tm = &tt;
|
||||
@@ -752,8 +752,8 @@ PGTYPESinterval_from_asc(char *str, char **endptr)
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN + MAXDATEFIELDS];
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
tm->tm_year = 0;
|
||||
tm->tm_mon = 0;
|
||||
@@ -791,7 +791,7 @@ PGTYPESinterval_from_asc(char *str, char **endptr)
|
||||
errno = PGTYPES_INTVL_BAD_INTERVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -802,7 +802,7 @@ PGTYPESinterval_to_asc(Interval *span)
|
||||
*tm = &tt;
|
||||
fsec_t fsec;
|
||||
char buf[MAXDATELEN + 1];
|
||||
int DateStyle=0;
|
||||
int DateStyle = 0;
|
||||
|
||||
if (interval2tm(*span, tm, &fsec) != 0)
|
||||
{
|
||||
@@ -815,11 +815,11 @@ PGTYPESinterval_to_asc(Interval *span)
|
||||
errno = PGTYPES_INTVL_BAD_INTERVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pgtypes_strdup(buf);
|
||||
|
||||
return pgtypes_strdup(buf);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
PGTYPESinterval_copy(Interval *intvlsrc, Interval *intrcldest)
|
||||
{
|
||||
intrcldest->time = intvlsrc->time;
|
||||
@@ -827,4 +827,3 @@ PGTYPESinterval_copy(Interval *intvlsrc, Interval *intrcldest)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -5,17 +5,17 @@
|
||||
#include "extern.h"
|
||||
#include "pgtypes_error.h"
|
||||
|
||||
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define Min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define Min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define init_var(v) memset(v,0,sizeof(Numeric))
|
||||
#define init_var(v) memset(v,0,sizeof(Numeric))
|
||||
|
||||
#define digitbuf_alloc(size) ((NumericDigit *) pgtypes_alloc(size))
|
||||
#define digitbuf_free(buf) \
|
||||
do { \
|
||||
if ((buf) != NULL) \
|
||||
free(buf); \
|
||||
} while (0)
|
||||
#define digitbuf_free(buf) \
|
||||
do { \
|
||||
if ((buf) != NULL) \
|
||||
free(buf); \
|
||||
} while (0)
|
||||
|
||||
#include "pgtypes_numeric.h"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
* typmod field.
|
||||
* ----------
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
apply_typmod(Numeric *var, long typmod)
|
||||
{
|
||||
int precision;
|
||||
@@ -37,7 +37,7 @@ apply_typmod(Numeric *var, long typmod)
|
||||
|
||||
/* Do nothing if we have a default typmod (-1) */
|
||||
if (typmod < (long) (VARHDRSZ))
|
||||
return(0);
|
||||
return (0);
|
||||
|
||||
typmod -= VARHDRSZ;
|
||||
precision = (typmod >> 16) & 0xffff;
|
||||
@@ -102,9 +102,9 @@ apply_typmod(Numeric *var, long typmod)
|
||||
#endif
|
||||
|
||||
/* ----------
|
||||
* alloc_var() -
|
||||
*
|
||||
* Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
|
||||
* alloc_var() -
|
||||
*
|
||||
* Allocate a digit buffer of ndigits digits (plus a spare digit for rounding)
|
||||
* ----------
|
||||
*/
|
||||
static int
|
||||
@@ -120,17 +120,16 @@ alloc_var(Numeric *var, int ndigits)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Numeric *
|
||||
Numeric *
|
||||
PGTYPESnumeric_new(void)
|
||||
{
|
||||
Numeric *var;
|
||||
|
||||
if ((var = (Numeric *)pgtypes_alloc(sizeof(Numeric))) == NULL)
|
||||
Numeric *var;
|
||||
|
||||
if ((var = (Numeric *) pgtypes_alloc(sizeof(Numeric))) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (alloc_var(var, 0) < 0) {
|
||||
if (alloc_var(var, 0) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
@@ -141,11 +140,11 @@ PGTYPESnumeric_new(void)
|
||||
* Parse a string and put the number into a variable
|
||||
* ----------
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
{
|
||||
bool have_dp = FALSE;
|
||||
int i = 0;
|
||||
bool have_dp = FALSE;
|
||||
int i = 0;
|
||||
|
||||
*ptr = str;
|
||||
while (*(*ptr))
|
||||
@@ -182,7 +181,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
|
||||
if (!isdigit((unsigned char) *(*ptr)))
|
||||
{
|
||||
errno=PGTYPES_NUM_BAD_NUMERIC;
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -259,7 +258,7 @@ set_var_from_str(char *str, char **ptr, Numeric *dest)
|
||||
dest->weight = 0;
|
||||
|
||||
dest->rscale = dest->dscale;
|
||||
return(0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +307,7 @@ get_str_from_var(Numeric *var, int dscale)
|
||||
/*
|
||||
* Allocate space for the result
|
||||
*/
|
||||
if ((str = (char *)pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL)
|
||||
if ((str = (char *) pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL)
|
||||
return NULL;
|
||||
cp = str;
|
||||
|
||||
@@ -360,17 +359,18 @@ get_str_from_var(Numeric *var, int dscale)
|
||||
Numeric *
|
||||
PGTYPESnumeric_from_asc(char *str, char **endptr)
|
||||
{
|
||||
Numeric *value = (Numeric *)pgtypes_alloc(sizeof(Numeric));
|
||||
int ret;
|
||||
Numeric *value = (Numeric *) pgtypes_alloc(sizeof(Numeric));
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
long typmod = -1;
|
||||
long typmod = -1;
|
||||
#endif
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
if (!value)
|
||||
return (NULL);
|
||||
|
||||
|
||||
ret = set_var_from_str(str, ptr, value);
|
||||
if (ret)
|
||||
return (NULL);
|
||||
@@ -379,8 +379,8 @@ PGTYPESnumeric_from_asc(char *str, char **endptr)
|
||||
ret = apply_typmod(value, typmod);
|
||||
if (ret)
|
||||
return (NULL);
|
||||
#endif
|
||||
return(value);
|
||||
#endif
|
||||
return (value);
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -389,7 +389,7 @@ PGTYPESnumeric_to_asc(Numeric *num, int dscale)
|
||||
if (dscale <= 0)
|
||||
dscale = num->dscale;
|
||||
|
||||
return(get_str_from_var(num, dscale));
|
||||
return (get_str_from_var(num, dscale));
|
||||
}
|
||||
|
||||
/* ----------
|
||||
@@ -410,7 +410,7 @@ zero_var(Numeric *var)
|
||||
var->sign = NUMERIC_POS; /* anything but NAN... */
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PGTYPESnumeric_free(Numeric *var)
|
||||
{
|
||||
digitbuf_free(var->buf);
|
||||
@@ -913,7 +913,7 @@ PGTYPESnumeric_sub(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
* mul_var() -
|
||||
*
|
||||
* Multiplication on variable level. Product of var1 * var2 is stored
|
||||
* in result. Accuracy of result is determined by global_rscale.
|
||||
* in result. Accuracy of result is determined by global_rscale.
|
||||
* ----------
|
||||
*/
|
||||
int
|
||||
@@ -929,7 +929,7 @@ PGTYPESnumeric_mul(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
i1,
|
||||
i2;
|
||||
long sum = 0;
|
||||
int global_rscale = var1->rscale + var2->rscale;
|
||||
int global_rscale = var1->rscale + var2->rscale;
|
||||
|
||||
res_weight = var1->weight + var2->weight + 2;
|
||||
res_ndigits = var1->ndigits + var2->ndigits + 1;
|
||||
@@ -939,7 +939,7 @@ PGTYPESnumeric_mul(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
res_sign = NUMERIC_NEG;
|
||||
|
||||
if ((res_buf = digitbuf_alloc(res_ndigits)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
res_digits = res_buf;
|
||||
memset(res_digits, 0, res_ndigits);
|
||||
|
||||
@@ -1054,8 +1054,8 @@ select_div_scale(Numeric *var1, Numeric *var2, int *rscale)
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate weight of quotient. If the two first digits are equal,
|
||||
* we can't be sure, but assume that var1 is less than var2.
|
||||
* Estimate weight of quotient. If the two first digits are equal, we
|
||||
* can't be sure, but assume that var1 is less than var2.
|
||||
*/
|
||||
qweight = weight1 - weight2;
|
||||
if (firstdigit1 <= firstdigit2)
|
||||
@@ -1081,8 +1081,8 @@ PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
int res_ndigits;
|
||||
int res_sign;
|
||||
int res_weight;
|
||||
Numeric dividend;
|
||||
Numeric divisor[10];
|
||||
Numeric dividend;
|
||||
Numeric divisor[10];
|
||||
int ndigits_tmp;
|
||||
int weight_tmp;
|
||||
int rscale_tmp;
|
||||
@@ -1093,16 +1093,16 @@ PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
long first_div;
|
||||
int first_nextdigit;
|
||||
int stat = 0;
|
||||
int rscale;
|
||||
int res_dscale = select_div_scale(var1, var2, &rscale);
|
||||
|
||||
int rscale;
|
||||
int res_dscale = select_div_scale(var1, var2, &rscale);
|
||||
|
||||
/*
|
||||
* First of all division by zero check
|
||||
*/
|
||||
ndigits_tmp = var2->ndigits + 1;
|
||||
if (ndigits_tmp == 1)
|
||||
{
|
||||
errno= PGTYPES_NUM_DIVIDE_ZERO;
|
||||
errno = PGTYPES_NUM_DIVIDE_ZERO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1281,29 +1281,30 @@ PGTYPESnumeric_div(Numeric *var1, Numeric *var2, Numeric *result)
|
||||
|
||||
|
||||
int
|
||||
PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) {
|
||||
PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2)
|
||||
{
|
||||
|
||||
/* use cmp_abs function to calculate the result */
|
||||
|
||||
/* both are positive: normal comparation with cmp_abs */
|
||||
if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS) {
|
||||
if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_POS)
|
||||
return cmp_abs(var1, var2);
|
||||
}
|
||||
|
||||
/* both are negative: return the inverse of the normal comparation */
|
||||
if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG) {
|
||||
/* instead of inverting the result, we invert the paramter
|
||||
* ordering */
|
||||
if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_NEG)
|
||||
{
|
||||
/*
|
||||
* instead of inverting the result, we invert the paramter
|
||||
* ordering
|
||||
*/
|
||||
return cmp_abs(var2, var1);
|
||||
}
|
||||
|
||||
/* one is positive, one is negative: trivial */
|
||||
if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG) {
|
||||
if (var1->sign == NUMERIC_POS && var2->sign == NUMERIC_NEG)
|
||||
return 1;
|
||||
}
|
||||
if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS) {
|
||||
if (var1->sign == NUMERIC_NEG && var2->sign == NUMERIC_POS)
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return INT_MAX;
|
||||
@@ -1311,67 +1312,79 @@ PGTYPESnumeric_cmp(Numeric *var1, Numeric *var2) {
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_from_int(signed int int_val, Numeric *var) {
|
||||
PGTYPESnumeric_from_int(signed int int_val, Numeric *var)
|
||||
{
|
||||
/* implicit conversion */
|
||||
signed long int long_int = int_val;
|
||||
|
||||
return PGTYPESnumeric_from_long(long_int, var);
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_from_long(signed long int long_val, Numeric *var) {
|
||||
PGTYPESnumeric_from_long(signed long int long_val, Numeric *var)
|
||||
{
|
||||
/* calculate the size of the long int number */
|
||||
/* a number n needs log_10 n digits */
|
||||
/* however we multiply by 10 each time and compare instead of
|
||||
* calculating the logarithm */
|
||||
|
||||
int size = 0;
|
||||
int i;
|
||||
/*
|
||||
* however we multiply by 10 each time and compare instead of
|
||||
* calculating the logarithm
|
||||
*/
|
||||
|
||||
int size = 0;
|
||||
int i;
|
||||
signed long int abs_long_val = long_val;
|
||||
signed long int extract;
|
||||
signed long int reach_limit;
|
||||
|
||||
if (abs_long_val < 0) {
|
||||
|
||||
if (abs_long_val < 0)
|
||||
{
|
||||
abs_long_val *= -1;
|
||||
var->sign = NUMERIC_NEG;
|
||||
} else {
|
||||
var->sign = NUMERIC_POS;
|
||||
}
|
||||
else
|
||||
var->sign = NUMERIC_POS;
|
||||
|
||||
reach_limit = 1;
|
||||
do {
|
||||
do
|
||||
{
|
||||
size++;
|
||||
reach_limit *= 10;
|
||||
} while ((reach_limit-1) < abs_long_val);
|
||||
} while ((reach_limit - 1) < abs_long_val);
|
||||
|
||||
/* always add a .0 */
|
||||
size++;
|
||||
|
||||
if (alloc_var(var, size) < 0) {
|
||||
if (alloc_var(var, size) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
var->rscale = 1;
|
||||
var->dscale = 1;
|
||||
var->weight = size - 2;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
reach_limit /= 10;
|
||||
extract = abs_long_val - (abs_long_val % reach_limit);
|
||||
var->digits[i] = extract / reach_limit;
|
||||
abs_long_val -= extract;
|
||||
i++;
|
||||
/* we can abandon if abs_long_val reaches 0, because the
|
||||
* memory is initialized properly and filled with '0', so
|
||||
* converting 10000 in only one step is no problem */
|
||||
|
||||
/*
|
||||
* we can abandon if abs_long_val reaches 0, because the memory is
|
||||
* initialized properly and filled with '0', so converting 10000
|
||||
* in only one step is no problem
|
||||
*/
|
||||
} while (abs_long_val > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_copy(Numeric *src, Numeric *dst) {
|
||||
int i;
|
||||
PGTYPESnumeric_copy(Numeric *src, Numeric *dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
zero_var(dst);
|
||||
|
||||
@@ -1383,9 +1396,8 @@ PGTYPESnumeric_copy(Numeric *src, Numeric *dst) {
|
||||
if (alloc_var(dst, src->ndigits) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < src->ndigits; i++) {
|
||||
for (i = 0; i < src->ndigits; i++)
|
||||
dst->digits[i] = src->digits[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1393,12 +1405,12 @@ PGTYPESnumeric_copy(Numeric *src, Numeric *dst) {
|
||||
int
|
||||
PGTYPESnumeric_from_double(double d, Numeric *dst)
|
||||
{
|
||||
char buffer[100];
|
||||
Numeric *tmp;
|
||||
|
||||
char buffer[100];
|
||||
Numeric *tmp;
|
||||
|
||||
if (sprintf(buffer, "%f", d) == 0)
|
||||
return -1;
|
||||
|
||||
|
||||
if ((tmp = PGTYPESnumeric_from_asc(buffer, NULL)) == NULL)
|
||||
return -1;
|
||||
if (PGTYPESnumeric_copy(tmp, dst) != 0)
|
||||
@@ -1425,17 +1437,18 @@ numericvar_to_double_no_overflow(Numeric *var, double *dp)
|
||||
free(tmp);
|
||||
errno = PGTYPES_NUM_BAD_NUMERIC;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*dp = val;
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_to_double(Numeric* nv, double* dp) {
|
||||
double tmp;
|
||||
int i;
|
||||
|
||||
PGTYPESnumeric_to_double(Numeric *nv, double *dp)
|
||||
{
|
||||
double tmp;
|
||||
int i;
|
||||
|
||||
if ((i = numericvar_to_double_no_overflow(nv, &tmp)) != 0)
|
||||
return -1;
|
||||
*dp = tmp;
|
||||
@@ -1443,72 +1456,79 @@ PGTYPESnumeric_to_double(Numeric* nv, double* dp) {
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_to_int(Numeric* nv, int* ip) {
|
||||
long l;
|
||||
int i;
|
||||
|
||||
PGTYPESnumeric_to_int(Numeric *nv, int *ip)
|
||||
{
|
||||
long l;
|
||||
int i;
|
||||
|
||||
if ((i = PGTYPESnumeric_to_long(nv, &l)) != 0)
|
||||
return i;
|
||||
|
||||
if (l < -INT_MAX || l > INT_MAX) {
|
||||
if (l < -INT_MAX || l > INT_MAX)
|
||||
{
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*ip = (int) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_to_long(Numeric* nv, long* lp) {
|
||||
int i;
|
||||
long l = 0;
|
||||
PGTYPESnumeric_to_long(Numeric *nv, long *lp)
|
||||
{
|
||||
int i;
|
||||
long l = 0;
|
||||
|
||||
for (i = 1; i < nv->weight + 2; i++) {
|
||||
for (i = 1; i < nv->weight + 2; i++)
|
||||
{
|
||||
l *= 10;
|
||||
l += nv->buf[i];
|
||||
}
|
||||
if (nv->buf[i] >= 5) {
|
||||
if (nv->buf[i] >= 5)
|
||||
{
|
||||
/* round up */
|
||||
l++;
|
||||
}
|
||||
if (l > LONG_MAX || l < 0) {
|
||||
if (l > LONG_MAX || l < 0)
|
||||
{
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nv->sign == NUMERIC_NEG) {
|
||||
|
||||
if (nv->sign == NUMERIC_NEG)
|
||||
l *= -1;
|
||||
}
|
||||
*lp = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_to_decimal(Numeric *src, Decimal *dst) {
|
||||
int i;
|
||||
PGTYPESnumeric_to_decimal(Numeric *src, Decimal * dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (src->ndigits > DECSIZE) {
|
||||
if (src->ndigits > DECSIZE)
|
||||
{
|
||||
errno = PGTYPES_NUM_OVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dst->weight = src->weight;
|
||||
dst->rscale = src->rscale;
|
||||
dst->dscale = src->dscale;
|
||||
dst->sign = src->sign;
|
||||
dst->ndigits = src->ndigits;
|
||||
|
||||
for (i = 0; i < src->ndigits; i++) {
|
||||
for (i = 0; i < src->ndigits; i++)
|
||||
dst->digits[i] = src->digits[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPESnumeric_from_decimal(Decimal *src, Numeric *dst) {
|
||||
int i;
|
||||
PGTYPESnumeric_from_decimal(Decimal * src, Numeric *dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
zero_var(dst);
|
||||
|
||||
@@ -1520,9 +1540,8 @@ PGTYPESnumeric_from_decimal(Decimal *src, Numeric *dst) {
|
||||
if (alloc_var(dst, src->ndigits) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < src->ndigits; i++) {
|
||||
for (i = 0; i < src->ndigits; i++)
|
||||
dst->digits[i] = src->digits[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@
|
||||
#include "pgtypes_date.h"
|
||||
#include "datetime.h"
|
||||
|
||||
int PGTYPEStimestamp_defmt_scan(char**, char*, Timestamp *, int*, int*, int*,
|
||||
int*, int*, int*, int*);
|
||||
int PGTYPEStimestamp_defmt_scan(char **, char *, Timestamp *, int *, int *, int *,
|
||||
int *, int *, int *, int *);
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
static int64
|
||||
@@ -89,7 +89,8 @@ static Timestamp
|
||||
SetEpochTimestamp(void)
|
||||
{
|
||||
Timestamp dt;
|
||||
struct tm tt, *tm = &tt;
|
||||
struct tm tt,
|
||||
*tm = &tt;
|
||||
|
||||
GetEpochTime(tm);
|
||||
tm2timestamp(tm, 0, NULL, &dt);
|
||||
@@ -101,6 +102,7 @@ dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 time;
|
||||
|
||||
#else
|
||||
double time;
|
||||
#endif
|
||||
@@ -142,8 +144,8 @@ static int
|
||||
timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn)
|
||||
{
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int date,
|
||||
date0;
|
||||
int date,
|
||||
date0;
|
||||
int64 time;
|
||||
|
||||
#else
|
||||
@@ -255,8 +257,8 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn)
|
||||
} /* timestamp2tm() */
|
||||
|
||||
/* EncodeSpecialTimestamp()
|
||||
* * Convert reserved timestamp data type to string.
|
||||
* */
|
||||
* * Convert reserved timestamp data type to string.
|
||||
* */
|
||||
static int
|
||||
EncodeSpecialTimestamp(Timestamp dt, char *str)
|
||||
{
|
||||
@@ -274,21 +276,24 @@ Timestamp
|
||||
PGTYPEStimestamp_from_asc(char *str, char **endptr)
|
||||
{
|
||||
Timestamp result;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
int64 noresult = 0;
|
||||
|
||||
#else
|
||||
double noresult = 0.0;
|
||||
#endif
|
||||
fsec_t fsec;
|
||||
struct tm tt, *tm = &tt;
|
||||
int tz;
|
||||
int dtype;
|
||||
int nf;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
struct tm tt,
|
||||
*tm = &tt;
|
||||
int tz;
|
||||
int dtype;
|
||||
int nf;
|
||||
char *field[MAXDATEFIELDS];
|
||||
int ftype[MAXDATEFIELDS];
|
||||
char lowstr[MAXDATELEN + MAXDATEFIELDS];
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
char *realptr;
|
||||
char **ptr = (endptr != NULL) ? endptr : &realptr;
|
||||
|
||||
errno = 0;
|
||||
if (strlen(str) >= sizeof(lowstr))
|
||||
@@ -298,12 +303,12 @@ PGTYPEStimestamp_from_asc(char *str, char **endptr)
|
||||
}
|
||||
|
||||
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
|
||||
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0))
|
||||
{
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
}
|
||||
|
||||
errno = PGTYPES_TS_BAD_TIMESTAMP;
|
||||
return (noresult);
|
||||
}
|
||||
|
||||
switch (dtype)
|
||||
{
|
||||
case DTK_DATE:
|
||||
@@ -343,11 +348,13 @@ PGTYPEStimestamp_from_asc(char *str, char **endptr)
|
||||
char *
|
||||
PGTYPEStimestamp_to_asc(Timestamp tstamp)
|
||||
{
|
||||
struct tm tt, *tm = &tt;
|
||||
struct tm tt,
|
||||
*tm = &tt;
|
||||
char buf[MAXDATELEN + 1];
|
||||
char *tzn = NULL;
|
||||
char *tzn = NULL;
|
||||
fsec_t fsec;
|
||||
int DateStyle = 1; /* this defaults to ISO_DATES, shall we make it an option? */
|
||||
int DateStyle = 1; /* this defaults to ISO_DATES, shall we
|
||||
* make it an option? */
|
||||
|
||||
if (TIMESTAMP_NOT_FINITE(tstamp))
|
||||
EncodeSpecialTimestamp(tstamp, buf);
|
||||
@@ -362,31 +369,34 @@ PGTYPEStimestamp_to_asc(Timestamp tstamp)
|
||||
}
|
||||
|
||||
void
|
||||
PGTYPEStimestamp_current (Timestamp *ts)
|
||||
PGTYPEStimestamp_current(Timestamp *ts)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
|
||||
GetCurrentDateTime(&tm);
|
||||
tm2timestamp(&tm, 0, NULL, ts);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
char* output, int *pstr_len, char *fmtstr)
|
||||
dttofmtasc_replace(Timestamp *ts, Date dDate, int dow, struct tm * tm,
|
||||
char *output, int *pstr_len, char *fmtstr)
|
||||
{
|
||||
union un_fmt_comb replace_val;
|
||||
int replace_type;
|
||||
int i;
|
||||
char* p = fmtstr;
|
||||
char* q = output;
|
||||
int replace_type;
|
||||
int i;
|
||||
char *p = fmtstr;
|
||||
char *q = output;
|
||||
|
||||
while (*p) {
|
||||
if (*p == '%') {
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
p++;
|
||||
/* fix compiler warning */
|
||||
replace_type = PGTYPES_TYPE_NOTHING;
|
||||
switch (*p) {
|
||||
switch (*p)
|
||||
{
|
||||
case 'a':
|
||||
replace_val.str_val = pgtypes_date_weekdays_short[dow];
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
@@ -416,19 +426,21 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
replace_type = PGTYPES_TYPE_UINT_2_LZ;
|
||||
break;
|
||||
case 'D':
|
||||
/* ts, dDate, dow, tm is
|
||||
* information about the timestamp
|
||||
|
||||
/*
|
||||
* ts, dDate, dow, tm is information about the
|
||||
* timestamp
|
||||
*
|
||||
* q is the start of the current
|
||||
* output buffer
|
||||
* q is the start of the current output buffer
|
||||
*
|
||||
* pstr_len is a pointer to the
|
||||
* remaining size of output, i.e.
|
||||
* the size of q */
|
||||
* pstr_len is a pointer to the remaining size of output,
|
||||
* i.e. the size of q
|
||||
*/
|
||||
i = dttofmtasc_replace(ts, dDate, dow, tm,
|
||||
q, pstr_len,
|
||||
"%m/%d/%y");
|
||||
if (i) { return i; }
|
||||
q, pstr_len,
|
||||
"%m/%d/%y");
|
||||
if (i)
|
||||
return i;
|
||||
break;
|
||||
case 'e':
|
||||
replace_val.uint_val = tm->tm_mday;
|
||||
@@ -436,19 +448,23 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
break;
|
||||
case 'E':
|
||||
{
|
||||
char tmp[4] = "%Ex";
|
||||
char tmp[4] = "%Ex";
|
||||
|
||||
p++;
|
||||
if (*p == '\0') {
|
||||
if (*p == '\0')
|
||||
return -1;
|
||||
}
|
||||
tmp[2] = *p;
|
||||
/* XXX: fall back to strftime */
|
||||
/* strftime's month is 0
|
||||
* based, ours is 1 based */
|
||||
|
||||
/*
|
||||
* strftime's month is 0 based, ours is 1 based
|
||||
*/
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, tmp, tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -460,8 +476,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%G", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -471,12 +489,15 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
case 'g':
|
||||
/* XXX: fall back to strftime */
|
||||
{
|
||||
char *fmt = "%g"; /* Keep compiler quiet about 2-digit year */
|
||||
|
||||
char *fmt = "%g"; /* Keep compiler quiet
|
||||
* about 2-digit year */
|
||||
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, fmt, tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -517,32 +538,32 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
replace_type = PGTYPES_TYPE_CHAR;
|
||||
break;
|
||||
case 'p':
|
||||
if (tm->tm_hour < 12) {
|
||||
if (tm->tm_hour < 12)
|
||||
replace_val.str_val = "AM";
|
||||
} else {
|
||||
else
|
||||
replace_val.str_val = "PM";
|
||||
}
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
break;
|
||||
case 'P':
|
||||
if (tm->tm_hour < 12) {
|
||||
if (tm->tm_hour < 12)
|
||||
replace_val.str_val = "am";
|
||||
} else {
|
||||
else
|
||||
replace_val.str_val = "pm";
|
||||
}
|
||||
replace_type = PGTYPES_TYPE_STRING_CONSTANT;
|
||||
break;
|
||||
case 'r':
|
||||
i = dttofmtasc_replace(ts, dDate, dow, tm,
|
||||
q, pstr_len,
|
||||
"%I:%M:%S %p");
|
||||
if (i) { return i; }
|
||||
q, pstr_len,
|
||||
"%I:%M:%S %p");
|
||||
if (i)
|
||||
return i;
|
||||
break;
|
||||
case 'R':
|
||||
i = dttofmtasc_replace(ts, dDate, dow, tm,
|
||||
q, pstr_len,
|
||||
"%H:%M");
|
||||
if (i) { return i; }
|
||||
q, pstr_len,
|
||||
"%H:%M");
|
||||
if (i)
|
||||
return i;
|
||||
break;
|
||||
case 's':
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
@@ -563,12 +584,14 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
break;
|
||||
case 'T':
|
||||
i = dttofmtasc_replace(ts, dDate, dow, tm,
|
||||
q, pstr_len,
|
||||
"%H:%M:%S");
|
||||
if (i) { return i; }
|
||||
q, pstr_len,
|
||||
"%H:%M:%S");
|
||||
if (i)
|
||||
return i;
|
||||
break;
|
||||
case 'u':
|
||||
if (dow == 0) { dow = 7; }
|
||||
if (dow == 0)
|
||||
dow = 7;
|
||||
replace_val.uint_val = dow;
|
||||
replace_type = PGTYPES_TYPE_UINT;
|
||||
break;
|
||||
@@ -576,8 +599,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%U", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -587,8 +612,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
case 'V':
|
||||
/* XXX: fall back to strftime */
|
||||
i = strftime(q, *pstr_len, "%V", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -602,8 +629,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%U", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -613,12 +642,15 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
case 'x':
|
||||
/* XXX: fall back to strftime */
|
||||
{
|
||||
char *fmt = "%x"; /* Keep compiler quiet about 2-digit year */
|
||||
char *fmt = "%x"; /* Keep compiler quiet
|
||||
* about 2-digit year */
|
||||
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, fmt, tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -630,8 +662,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%X", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -650,8 +684,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%z", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -662,8 +698,10 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
/* XXX: fall back to strftime */
|
||||
tm->tm_mon -= 1;
|
||||
i = strftime(q, *pstr_len, "%Z", tm);
|
||||
if (i == 0) { return -1; }
|
||||
while (*q) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
while (*q)
|
||||
{
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
@@ -676,41 +714,53 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
break;
|
||||
case '\0':
|
||||
/* fmtstr: blabla%' */
|
||||
/* this is not compliant to the
|
||||
* specification */
|
||||
|
||||
/*
|
||||
* this is not compliant to the specification
|
||||
*/
|
||||
return -1;
|
||||
default:
|
||||
/* if we don't know the pattern, we
|
||||
* just copy it */
|
||||
if (*pstr_len > 1) {
|
||||
|
||||
/*
|
||||
* if we don't know the pattern, we just copy it
|
||||
*/
|
||||
if (*pstr_len > 1)
|
||||
{
|
||||
*q = '%';
|
||||
q++; (*pstr_len)--;
|
||||
if (*pstr_len > 1) {
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
if (*pstr_len > 1)
|
||||
{
|
||||
*q = *p;
|
||||
q++; (*pstr_len)--;
|
||||
} else {
|
||||
q++;
|
||||
(*pstr_len)--;
|
||||
}
|
||||
else
|
||||
{
|
||||
*q = '\0';
|
||||
return -1;
|
||||
}
|
||||
*q = '\0';
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
i = pgtypes_fmt_replace(replace_val, replace_type, &q, pstr_len);
|
||||
if (i) {
|
||||
if (i)
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
if (*pstr_len > 1) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*pstr_len > 1)
|
||||
{
|
||||
*q = *p;
|
||||
(*pstr_len)--;
|
||||
q++;
|
||||
*q = '\0';
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
@@ -719,12 +769,12 @@ dttofmtasc_replace (Timestamp *ts, Date dDate, int dow, struct tm* tm,
|
||||
|
||||
|
||||
int
|
||||
PGTYPEStimestamp_fmt_asc (Timestamp *ts, char *output, int str_len, char *fmtstr)
|
||||
PGTYPEStimestamp_fmt_asc(Timestamp *ts, char *output, int str_len, char *fmtstr)
|
||||
{
|
||||
struct tm tm;
|
||||
fsec_t fsec;
|
||||
Date dDate;
|
||||
int dow;
|
||||
struct tm tm;
|
||||
fsec_t fsec;
|
||||
Date dDate;
|
||||
int dow;
|
||||
|
||||
dDate = PGTYPESdate_from_timestamp(*ts);
|
||||
dow = PGTYPESdate_dayofweek(dDate);
|
||||
@@ -734,12 +784,10 @@ PGTYPEStimestamp_fmt_asc (Timestamp *ts, char *output, int str_len, char *fmtstr
|
||||
}
|
||||
|
||||
int
|
||||
PGTYPEStimestamp_sub (Timestamp *ts1, Timestamp *ts2, Interval *iv)
|
||||
PGTYPEStimestamp_sub(Timestamp *ts1, Timestamp *ts2, Interval *iv)
|
||||
{
|
||||
if (TIMESTAMP_NOT_FINITE(*ts1) || TIMESTAMP_NOT_FINITE(*ts2))
|
||||
{
|
||||
return PGTYPES_TS_ERR_EINFTIME;
|
||||
}
|
||||
else
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
iv->time = (ts1 - ts2);
|
||||
@@ -752,28 +800,40 @@ PGTYPEStimestamp_sub (Timestamp *ts1, Timestamp *ts2, Interval *iv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PGTYPEStimestamp_defmt_asc(char* str, char *fmt, Timestamp *d) {
|
||||
int year, month, day;
|
||||
int hour, minute, second;
|
||||
int tz;
|
||||
int
|
||||
PGTYPEStimestamp_defmt_asc(char *str, char *fmt, Timestamp *d)
|
||||
{
|
||||
int year,
|
||||
month,
|
||||
day;
|
||||
int hour,
|
||||
minute,
|
||||
second;
|
||||
int tz;
|
||||
|
||||
int i;
|
||||
char* mstr;
|
||||
char* mfmt;
|
||||
int i;
|
||||
char *mstr;
|
||||
char *mfmt;
|
||||
|
||||
if (!fmt) {
|
||||
if (!fmt)
|
||||
fmt = "%Y-%m-%d %H:%M:%S";
|
||||
}
|
||||
if (!fmt[0]) {
|
||||
if (!fmt[0])
|
||||
return 1;
|
||||
}
|
||||
|
||||
mstr = pgtypes_strdup(str);
|
||||
mfmt = pgtypes_strdup(fmt);
|
||||
/* initialize with impossible values so that we can see if the
|
||||
* fields where specified at all */
|
||||
|
||||
/*
|
||||
* initialize with impossible values so that we can see if the fields
|
||||
* where specified at all
|
||||
*/
|
||||
/* XXX ambiguity with 1 BC for year? */
|
||||
year = -1; month = -1; day = -1; hour = 0; minute = -1; second = -1;
|
||||
year = -1;
|
||||
month = -1;
|
||||
day = -1;
|
||||
hour = 0;
|
||||
minute = -1;
|
||||
second = -1;
|
||||
tz = 0;
|
||||
|
||||
i = PGTYPEStimestamp_defmt_scan(&mstr, mfmt, d, &year, &month, &day, &hour, &minute, &second, &tz);
|
||||
@@ -781,4 +841,3 @@ int PGTYPEStimestamp_defmt_asc(char* str, char *fmt, Timestamp *d) {
|
||||
free(mfmt);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@@ -28,24 +28,24 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"enum", SQL_ENUM},
|
||||
{"extern", S_EXTERN},
|
||||
{"float", FLOAT_P},
|
||||
{"hour", HOUR_P},
|
||||
{"hour", HOUR_P},
|
||||
{"int", INT_P},
|
||||
{"long", SQL_LONG},
|
||||
{"minute", MINUTE_P},
|
||||
{"month", MONTH_P},
|
||||
{"month", MONTH_P},
|
||||
{"register", S_REGISTER},
|
||||
{"second", SECOND_P},
|
||||
{"second", SECOND_P},
|
||||
{"short", SQL_SHORT},
|
||||
{"signed", SQL_SIGNED},
|
||||
{"static", S_STATIC},
|
||||
{"struct", SQL_STRUCT},
|
||||
{"to", TO},
|
||||
{"to", TO},
|
||||
{"typedef", S_TYPEDEF},
|
||||
{"union", UNION},
|
||||
{"unsigned", SQL_UNSIGNED},
|
||||
{"varchar", VARCHAR},
|
||||
{"volatile", S_VOLATILE},
|
||||
{"year", YEAR_P},
|
||||
{"year", YEAR_P},
|
||||
};
|
||||
|
||||
ScanKeyword *
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.76 2003/08/01 08:21:04 meskes Exp $ */
|
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.77 2003/08/04 00:43:33 momjian Exp $ */
|
||||
|
||||
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
|
||||
/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
|
||||
@@ -23,7 +23,7 @@ int ret_value = 0,
|
||||
system_includes = false,
|
||||
force_indicator = true;
|
||||
|
||||
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
|
||||
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
|
||||
|
||||
struct _include_path *include_paths = NULL;
|
||||
struct cursor *cur = NULL;
|
||||
@@ -49,7 +49,7 @@ help(const char *progname)
|
||||
" \"INFORMIX\"\n"
|
||||
" \"INFORMIX_SE\"\n");
|
||||
printf(" -r <option> specify runtime behaviour\n"
|
||||
" option may be only \"no_indicator\" at the moment\n");
|
||||
" option may be only \"no_indicator\" at the moment\n");
|
||||
printf(" -D SYMBOL define SYMBOL\n");
|
||||
printf(" -I DIRECTORY search DIRECTORY for include files\n");
|
||||
printf(" -o OUTFILE write result to OUTFILE\n");
|
||||
@@ -65,7 +65,8 @@ help(const char *progname)
|
||||
static void
|
||||
add_include_path(char *path)
|
||||
{
|
||||
struct _include_path *ip = include_paths, *new;
|
||||
struct _include_path *ip = include_paths,
|
||||
*new;
|
||||
|
||||
new = mm_alloc(sizeof(struct _include_path));
|
||||
new->path = path;
|
||||
@@ -75,7 +76,7 @@ add_include_path(char *path)
|
||||
include_paths = new;
|
||||
else
|
||||
{
|
||||
for (;ip->next != NULL; ip=ip->next);
|
||||
for (; ip->next != NULL; ip = ip->next);
|
||||
ip->next = new;
|
||||
}
|
||||
}
|
||||
@@ -84,21 +85,22 @@ static void
|
||||
add_preprocessor_define(char *define)
|
||||
{
|
||||
struct _defines *pd = defines;
|
||||
char *ptr, *define_copy = mm_strdup(define);
|
||||
|
||||
char *ptr,
|
||||
*define_copy = mm_strdup(define);
|
||||
|
||||
defines = mm_alloc(sizeof(struct _defines));
|
||||
|
||||
|
||||
/* look for = sign */
|
||||
ptr = strchr(define_copy, '=');
|
||||
if (ptr != NULL)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
char *tmp;
|
||||
|
||||
/* symbol gets a value */
|
||||
for (tmp=ptr-1; *tmp == ' '; tmp--);
|
||||
for (tmp = ptr - 1; *tmp == ' '; tmp--);
|
||||
tmp[1] = '\0';
|
||||
defines->old = define_copy;
|
||||
defines->new = ptr+1;
|
||||
defines->new = ptr + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -141,11 +143,11 @@ main(int argc, char *const argv[])
|
||||
switch (c)
|
||||
{
|
||||
case 'o':
|
||||
if (strcmp(optarg, "-") == 0)
|
||||
if (strcmp(optarg, "-") == 0)
|
||||
yyout = stdout;
|
||||
else
|
||||
yyout = fopen(optarg, PG_BINARY_W);
|
||||
|
||||
|
||||
if (yyout == NULL)
|
||||
perror(optarg);
|
||||
else
|
||||
@@ -179,7 +181,7 @@ main(int argc, char *const argv[])
|
||||
{
|
||||
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
|
||||
return ILLEGAL_OPTION;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (strcmp(optarg, "no_indicator") == 0)
|
||||
@@ -240,7 +242,7 @@ main(int argc, char *const argv[])
|
||||
/* If argv[fnr] is "-" we have to read from stdin */
|
||||
if (strcmp(argv[fnr], "-") == 0)
|
||||
{
|
||||
input_filename = mm_alloc(strlen("stdin")+1);
|
||||
input_filename = mm_alloc(strlen("stdin") + 1);
|
||||
strcpy(input_filename, "stdin");
|
||||
yyin = stdin;
|
||||
}
|
||||
@@ -265,7 +267,7 @@ main(int argc, char *const argv[])
|
||||
ptr2ext[3] = 'c';
|
||||
ptr2ext[4] = '\0';
|
||||
}
|
||||
|
||||
|
||||
yyin = fopen(input_filename, PG_BINARY_R);
|
||||
}
|
||||
|
||||
@@ -377,7 +379,7 @@ main(int argc, char *const argv[])
|
||||
|
||||
/* finally the actual connection */
|
||||
connection = NULL;
|
||||
|
||||
|
||||
/* initialize lex */
|
||||
lex_init();
|
||||
|
||||
@@ -387,7 +389,7 @@ main(int argc, char *const argv[])
|
||||
/* add some compatibility headers */
|
||||
if (INFORMIX_MODE)
|
||||
fprintf(yyout, "/* Needed for informix compatibility */\n#include <ecpg_informix.h>\n");
|
||||
|
||||
|
||||
fprintf(yyout, "/* End of automatic include section */\n");
|
||||
|
||||
/* and parse the source */
|
||||
|
@@ -96,8 +96,12 @@ extern ScanKeyword *ScanKeywordLookup(char *text);
|
||||
#define INDICATOR_NOT_STRUCT 6
|
||||
#define INDICATOR_NOT_SIMPLE 7
|
||||
|
||||
enum COMPAT_MODE { ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE};
|
||||
enum COMPAT_MODE
|
||||
{
|
||||
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
|
||||
};
|
||||
extern enum COMPAT_MODE compat;
|
||||
|
||||
#define INFORMIX_MODE (compat == ECPG_COMPAT_INFORMIX || compat == ECPG_COMPAT_INFORMIX_SE)
|
||||
|
||||
#endif /* _ECPG_PREPROC_EXTERN_H */
|
||||
#endif /* _ECPG_PREPROC_EXTERN_H */
|
||||
|
@@ -220,10 +220,10 @@ static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, c
|
||||
|
||||
void
|
||||
ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
|
||||
const char *ind_name, struct ECPGtype * ind_type,
|
||||
const char *prefix, const char *ind_prefix,
|
||||
char *arr_str_siz, const char *struct_sizeof,
|
||||
const char *ind_struct_sizeof)
|
||||
const char *ind_name, struct ECPGtype * ind_type,
|
||||
const char *prefix, const char *ind_prefix,
|
||||
char *arr_str_siz, const char *struct_sizeof,
|
||||
const char *ind_struct_sizeof)
|
||||
{
|
||||
switch (type->type)
|
||||
{
|
||||
@@ -238,20 +238,20 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
|
||||
case ECPGt_struct:
|
||||
case ECPGt_union:
|
||||
ECPGdump_a_struct(o, name,
|
||||
ind_name,
|
||||
type->size,
|
||||
type->u.element,
|
||||
(ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
|
||||
NULL, prefix, ind_prefix);
|
||||
ind_name,
|
||||
type->size,
|
||||
type->u.element,
|
||||
(ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
|
||||
NULL, prefix, ind_prefix);
|
||||
break;
|
||||
default:
|
||||
if (!IS_SIMPLE_TYPE(type->u.element->type))
|
||||
yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org");
|
||||
|
||||
ECPGdump_a_simple(o, name,
|
||||
type->u.element->type,
|
||||
type->u.element->type,
|
||||
type->u.element->size, type->size, NULL, prefix);
|
||||
|
||||
|
||||
if (ind_type != NULL)
|
||||
{
|
||||
if (ind_type->type == ECPGt_NO_INDICATOR)
|
||||
@@ -259,7 +259,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
|
||||
else
|
||||
{
|
||||
ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
|
||||
ind_type->u.element->size, ind_type->size, NULL, prefix);
|
||||
ind_type->u.element->size, ind_type->size, NULL, prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,22 +318,23 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
{
|
||||
char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
|
||||
char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1);
|
||||
|
||||
|
||||
switch (type)
|
||||
{
|
||||
/*
|
||||
* we have to use the & operator except for arrays and pointers
|
||||
*/
|
||||
|
||||
/*
|
||||
* we have to use the & operator except for arrays and
|
||||
* pointers
|
||||
*/
|
||||
|
||||
case ECPGt_varchar:
|
||||
|
||||
/*
|
||||
* we have to use the pointer except for arrays with given
|
||||
* bounds
|
||||
*/
|
||||
if (((atoi(arrsize) > 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
|
||||
siz == NULL)
|
||||
if (((atoi(arrsize) > 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
|
||||
siz == NULL)
|
||||
sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
|
||||
else
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
@@ -346,13 +347,13 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
|
||||
/*
|
||||
* we have to use the pointer except for arrays with given
|
||||
* bounds, ecpglib will distinguish between * and []
|
||||
* bounds, ecpglib will distinguish between * and []
|
||||
*/
|
||||
if ((atoi(varcharsize) > 1 ||
|
||||
(atoi(arrsize) > 0) ||
|
||||
(atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
|
||||
&& siz == NULL)
|
||||
(atoi(arrsize) > 0) ||
|
||||
(atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
|
||||
&& siz == NULL)
|
||||
sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
|
||||
else
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
@@ -362,7 +363,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
case ECPGt_numeric:
|
||||
|
||||
/*
|
||||
* we have to use a pointer here
|
||||
* we have to use a pointer here
|
||||
*/
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
sprintf(offset, "sizeof(Numeric)");
|
||||
@@ -370,7 +371,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
case ECPGt_interval:
|
||||
|
||||
/*
|
||||
* we have to use a pointer here
|
||||
* we have to use a pointer here
|
||||
*/
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
sprintf(offset, "sizeof(Interval)");
|
||||
@@ -378,7 +379,8 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
case ECPGt_date:
|
||||
|
||||
/*
|
||||
* we have to use a pointer and translate the variable type
|
||||
* we have to use a pointer and translate the variable
|
||||
* type
|
||||
*/
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
sprintf(offset, "sizeof(Date)");
|
||||
@@ -386,7 +388,8 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
case ECPGt_timestamp:
|
||||
|
||||
/*
|
||||
* we have to use a pointer and translate the variable type
|
||||
* we have to use a pointer and translate the variable
|
||||
* type
|
||||
*/
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
sprintf(offset, "sizeof(Date)");
|
||||
@@ -394,7 +397,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
case ECPGt_const:
|
||||
|
||||
/*
|
||||
* just dump the const as string
|
||||
* just dump the const as string
|
||||
*/
|
||||
sprintf(variable, "\"%s\"", name);
|
||||
sprintf(offset, "strlen(\"%s\")", name);
|
||||
@@ -405,9 +408,9 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
* we have to use the pointer except for arrays with given
|
||||
* bounds
|
||||
*/
|
||||
if (((atoi(arrsize) > 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
|
||||
siz == NULL)
|
||||
if (((atoi(arrsize) > 0) ||
|
||||
(atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
|
||||
siz == NULL)
|
||||
sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
|
||||
else
|
||||
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||
@@ -418,7 +421,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
|
||||
|
||||
if (atoi(arrsize) < 0)
|
||||
strcpy(arrsize, "1");
|
||||
|
||||
|
||||
if (siz == NULL || strcmp(arrsize, "0") == 0 || strcmp(arrsize, "1") == 0)
|
||||
fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, offset);
|
||||
else
|
||||
@@ -476,11 +479,11 @@ ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz,
|
||||
|
||||
for (p = type->u.members; p; p = p->next)
|
||||
{
|
||||
ECPGdump_a_type(o, p->name, p->type,
|
||||
(ind_p != NULL) ? ind_p->name : NULL,
|
||||
(ind_p != NULL) ? ind_p->type : NULL,
|
||||
prefix, ind_prefix, arrsiz, type->struct_sizeof,
|
||||
(ind_p != NULL) ? ind_type->struct_sizeof : NULL);
|
||||
ECPGdump_a_type(o, p->name, p->type,
|
||||
(ind_p != NULL) ? ind_p->name : NULL,
|
||||
(ind_p != NULL) ? ind_p->type : NULL,
|
||||
prefix, ind_prefix, arrsiz, type->struct_sizeof,
|
||||
(ind_p != NULL) ? ind_type->struct_sizeof : NULL);
|
||||
if (ind_p != NULL && ind_p != &struct_no_indicator)
|
||||
ind_p = ind_p->next;
|
||||
}
|
||||
|
@@ -14,16 +14,17 @@ struct ECPGstruct_member
|
||||
struct ECPGtype
|
||||
{
|
||||
enum ECPGttype type;
|
||||
char *size; /* For array it is the number of elements.
|
||||
* For varchar it is the maxsize of the
|
||||
* area. */
|
||||
char *struct_sizeof; /* For a struct this is the sizeof() type
|
||||
* as string */
|
||||
char *size; /* For array it is the number of elements.
|
||||
* For varchar it is the maxsize of the
|
||||
* area. */
|
||||
char *struct_sizeof; /* For a struct this is the sizeof() type
|
||||
* as string */
|
||||
union
|
||||
{
|
||||
struct ECPGtype *element; /* For an array this is the type
|
||||
* of the element */
|
||||
struct ECPGstruct_member *members; /* A pointer to a list of members. */
|
||||
* of the element */
|
||||
struct ECPGstruct_member *members; /* A pointer to a list of
|
||||
* members. */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -49,9 +50,9 @@ void ECPGfree_type(struct ECPGtype *);
|
||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||
the variable (required to do array fetches of structs).
|
||||
*/
|
||||
void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *,
|
||||
const char *, struct ECPGtype *, const char *,
|
||||
const char *, char *, const char *, const char *);
|
||||
void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *,
|
||||
const char *, struct ECPGtype *, const char *,
|
||||
const char *, char *, const char *, const char *);
|
||||
|
||||
/* A simple struct to keep a variable and its type. */
|
||||
struct ECPGtemp_type
|
||||
@@ -83,24 +84,24 @@ struct when
|
||||
|
||||
struct index
|
||||
{
|
||||
char *index1;
|
||||
char *index2;
|
||||
char *str;
|
||||
char *index1;
|
||||
char *index2;
|
||||
char *str;
|
||||
};
|
||||
|
||||
struct su_symbol
|
||||
{
|
||||
char *su;
|
||||
char *symbol;
|
||||
char *su;
|
||||
char *symbol;
|
||||
};
|
||||
|
||||
struct this_type
|
||||
{
|
||||
enum ECPGttype type_enum;
|
||||
char *type_str;
|
||||
char *type_dimension;
|
||||
char *type_index;
|
||||
char *type_sizeof;
|
||||
char *type_str;
|
||||
char *type_dimension;
|
||||
char *type_index;
|
||||
char *type_sizeof;
|
||||
};
|
||||
|
||||
struct _include_path
|
||||
@@ -182,4 +183,4 @@ typedef struct ScanKeyword
|
||||
int value;
|
||||
} ScanKeyword;
|
||||
|
||||
#endif /* _ECPG_PREPROC_TYPE_H */
|
||||
#endif /* _ECPG_PREPROC_TYPE_H */
|
||||
|
@@ -23,7 +23,8 @@ static struct variable *
|
||||
find_struct_member(char *name, char *str, struct ECPGstruct_member * members, int brace_level)
|
||||
{
|
||||
char *next = strpbrk(++str, ".-["),
|
||||
*end, c = '\0';
|
||||
*end,
|
||||
c = '\0';
|
||||
|
||||
if (next != NULL)
|
||||
{
|
||||
@@ -54,54 +55,64 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
|
||||
*next = c;
|
||||
if (c == '[')
|
||||
{
|
||||
int count;
|
||||
int count;
|
||||
|
||||
/* We don't care about what's inside the array braces
|
||||
* so just eat up the character */
|
||||
for (count=1, end=next+1; count; end++)
|
||||
/*
|
||||
* We don't care about what's inside the array braces
|
||||
* so just eat up the character
|
||||
*/
|
||||
for (count = 1, end = next + 1; count; end++)
|
||||
{
|
||||
switch (*end)
|
||||
{
|
||||
case '[': count++;
|
||||
break;
|
||||
case ']': count--;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
switch (*end)
|
||||
{
|
||||
case '[':
|
||||
count++;
|
||||
break;
|
||||
case ']':
|
||||
count--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else end = next;
|
||||
|
||||
else
|
||||
end = next;
|
||||
|
||||
switch (*end)
|
||||
{
|
||||
case '\0': /* found the end, but this time it has to be an array element */
|
||||
if (members->type->type != ECPGt_array)
|
||||
{
|
||||
snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
|
||||
mmerror(PARSE_ERROR, ET_FATAL, errortext);
|
||||
}
|
||||
|
||||
switch (members->type->u.element->type)
|
||||
{
|
||||
case ECPGt_array:
|
||||
return (new_variable(name, ECPGmake_array_type(members->type->u.element->u.element, members->type->u.element->size), brace_level));
|
||||
case ECPGt_struct:
|
||||
case ECPGt_union:
|
||||
return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->struct_sizeof), brace_level));
|
||||
default:
|
||||
return (new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size), brace_level));
|
||||
}
|
||||
break;
|
||||
case '-': return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
|
||||
break;
|
||||
case '.': if (members->type->type != ECPGt_array)
|
||||
return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
|
||||
else
|
||||
return (find_struct_member(name, next, members->type->u.members, brace_level));
|
||||
break;
|
||||
default : snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
|
||||
case '\0': /* found the end, but this time it has to
|
||||
* be an array element */
|
||||
if (members->type->type != ECPGt_array)
|
||||
{
|
||||
snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
|
||||
mmerror(PARSE_ERROR, ET_FATAL, errortext);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (members->type->u.element->type)
|
||||
{
|
||||
case ECPGt_array:
|
||||
return (new_variable(name, ECPGmake_array_type(members->type->u.element->u.element, members->type->u.element->size), brace_level));
|
||||
case ECPGt_struct:
|
||||
case ECPGt_union:
|
||||
return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->struct_sizeof), brace_level));
|
||||
default:
|
||||
return (new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size), brace_level));
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
|
||||
break;
|
||||
case '.':
|
||||
if (members->type->type != ECPGt_array)
|
||||
return (find_struct_member(name, end, members->type->u.element->u.members, brace_level));
|
||||
else
|
||||
return (find_struct_member(name, next, members->type->u.members, brace_level));
|
||||
break;
|
||||
default:
|
||||
snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name);
|
||||
mmerror(PARSE_ERROR, ET_FATAL, errortext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,33 +206,40 @@ find_simple(char *name)
|
||||
struct variable *
|
||||
find_variable(char *name)
|
||||
{
|
||||
char *next, *end;
|
||||
char *next,
|
||||
*end;
|
||||
struct variable *p;
|
||||
int count;
|
||||
int count;
|
||||
|
||||
next = strpbrk(name, ".[-");
|
||||
if (next)
|
||||
{
|
||||
if (*next == '[')
|
||||
{
|
||||
/* We don't care about what's inside the array braces
|
||||
* so just eat up the character */
|
||||
for (count=1, end=next+1; count; end++)
|
||||
/*
|
||||
* We don't care about what's inside the array braces so just
|
||||
* eat up the character
|
||||
*/
|
||||
for (count = 1, end = next + 1; count; end++)
|
||||
{
|
||||
switch (*end)
|
||||
{
|
||||
case '[': count++;
|
||||
break;
|
||||
case ']': count--;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
switch (*end)
|
||||
{
|
||||
case '[':
|
||||
count++;
|
||||
break;
|
||||
case ']':
|
||||
count--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*end == '.') p = find_struct(name, next, end);
|
||||
if (*end == '.')
|
||||
p = find_struct(name, next, end);
|
||||
else
|
||||
{
|
||||
char c = *next;
|
||||
|
||||
char c = *next;
|
||||
|
||||
*next = '\0';
|
||||
p = find_simple(name);
|
||||
*next = c;
|
||||
@@ -237,9 +255,11 @@ find_variable(char *name)
|
||||
}
|
||||
}
|
||||
}
|
||||
else p = find_struct(name, next, next);
|
||||
else
|
||||
p = find_struct(name, next, next);
|
||||
}
|
||||
else p = find_simple(name);
|
||||
else
|
||||
p = find_simple(name);
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
@@ -263,9 +283,10 @@ remove_variables(int brace_level)
|
||||
/* is it still referenced by a cursor? */
|
||||
struct cursor *ptr;
|
||||
|
||||
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
||||
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
||||
{
|
||||
struct arguments *varptr, *prevvar;
|
||||
struct arguments *varptr,
|
||||
*prevvar;
|
||||
|
||||
for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = varptr->next)
|
||||
{
|
||||
@@ -290,7 +311,7 @@ remove_variables(int brace_level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* remove it */
|
||||
if (p == allvariables)
|
||||
prev = allvariables = p->next;
|
||||
@@ -373,7 +394,7 @@ dump_variables(struct arguments * list, int mode)
|
||||
dump_variables(list->next, mode);
|
||||
|
||||
/* Then the current element and its indicator */
|
||||
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
|
||||
ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
|
||||
list->indicator->name, list->indicator->type,
|
||||
NULL, NULL, 0, NULL, NULL);
|
||||
|
||||
@@ -512,14 +533,17 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
|
||||
/* one index is the string length */
|
||||
if (atoi(*length) < 0)
|
||||
{
|
||||
/* make sure we return length = -1 for arrays without given bounds */
|
||||
/*
|
||||
* make sure we return length = -1 for arrays without
|
||||
* given bounds
|
||||
*/
|
||||
if (atoi(*dimension) < 0)
|
||||
*length = make_str("1");
|
||||
else if (atoi(*dimension) == 0)
|
||||
*length = make_str("-1");
|
||||
else
|
||||
else
|
||||
*length = *dimension;
|
||||
|
||||
|
||||
*dimension = make_str("-1");
|
||||
}
|
||||
break;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.71 2002/12/30 22:10:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.72 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -289,11 +289,11 @@ Pg_conndefaults(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *ar
|
||||
int
|
||||
Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
|
||||
{
|
||||
const char *pghost = NULL;
|
||||
const char *pgtty = NULL;
|
||||
const char *pgport = NULL;
|
||||
const char *pgoptions = NULL;
|
||||
const char *dbName;
|
||||
const char *pghost = NULL;
|
||||
const char *pgtty = NULL;
|
||||
const char *pgport = NULL;
|
||||
const char *pgoptions = NULL;
|
||||
const char *dbName;
|
||||
int i;
|
||||
PGconn *conn;
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pgtclCmds.h,v 1.29 2002/12/30 22:10:54 tgl Exp $
|
||||
* $Id: pgtclCmds.h,v 1.30 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -93,23 +93,23 @@ typedef struct Pg_ConnectionId_s
|
||||
/* registered Tcl functions */
|
||||
/* **************************/
|
||||
extern int Pg_conndefaults(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_connect(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_disconnect(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_exec(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_execute(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_select(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_result(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_open(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_close(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
|
||||
#ifdef PGTCL_USE_TCLOBJ
|
||||
extern int Pg_lo_read(ClientData cData, Tcl_Interp *interp, int objc,
|
||||
@@ -119,25 +119,25 @@ extern int Pg_lo_write(ClientData cData, Tcl_Interp *interp, int objc,
|
||||
|
||||
#else
|
||||
extern int Pg_lo_read(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_write(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
#endif
|
||||
extern int Pg_lo_lseek(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_creat(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_tell(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_unlink(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_import(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_lo_export(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_listen(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
extern int Pg_on_connection_loss(ClientData cData, Tcl_Interp *interp,
|
||||
int argc, CONST84 char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
|
||||
#endif /* PGTCLCMDS_H */
|
||||
|
@@ -13,7 +13,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.41 2003/03/25 02:44:36 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.42 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -296,14 +296,14 @@ PgDelConnectionId(DRIVER_DEL_PROTO)
|
||||
* the socket itself!
|
||||
*
|
||||
* XXX Unfortunately, while this works fine if we are closing due to
|
||||
* explicit pg_disconnect, all Tcl versions through 8.4.1 dump core
|
||||
* if we try to do it during interpreter shutdown. Not clear why.
|
||||
* For now, we kill the channel during pg_disconnect, but during interp
|
||||
* shutdown we just accept leakage of the (fairly small) amount of memory
|
||||
* taken for the channel state representation.
|
||||
* (Note we are not leaking a socket, since libpq closed that already.)
|
||||
* We tell the difference between pg_disconnect and interpreter shutdown
|
||||
* by testing for interp != NULL, which is an undocumented but apparently
|
||||
* explicit pg_disconnect, all Tcl versions through 8.4.1 dump core if
|
||||
* we try to do it during interpreter shutdown. Not clear why. For
|
||||
* now, we kill the channel during pg_disconnect, but during interp
|
||||
* shutdown we just accept leakage of the (fairly small) amount of
|
||||
* memory taken for the channel state representation. (Note we are not
|
||||
* leaking a socket, since libpq closed that already.) We tell the
|
||||
* difference between pg_disconnect and interpreter shutdown by
|
||||
* testing for interp != NULL, which is an undocumented but apparently
|
||||
* safe way to tell.
|
||||
*/
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
|
@@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pgtclId.h,v 1.22 2002/12/30 22:10:54 tgl Exp $
|
||||
* $Id: pgtclId.h,v 1.23 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,8 +39,8 @@ extern PGconn *PgGetConnectionId(Tcl_Interp *interp, CONST84 char *id,
|
||||
extern int PgDelConnectionId(DRIVER_DEL_PROTO);
|
||||
extern int PgOutputProc(DRIVER_OUTPUT_PROTO);
|
||||
extern int PgInputProc(DRIVER_INPUT_PROTO);
|
||||
extern int PgSetResultId(Tcl_Interp *interp, CONST84 char *connid,
|
||||
PGresult *res);
|
||||
extern int PgSetResultId(Tcl_Interp *interp, CONST84 char *connid,
|
||||
PGresult *res);
|
||||
extern PGresult *PgGetResultId(Tcl_Interp *interp, CONST84 char *id);
|
||||
extern void PgDelResultId(Tcl_Interp *interp, CONST84 char *id);
|
||||
extern int PgGetConnByResultId(Tcl_Interp *interp, CONST84 char *resid);
|
||||
|
@@ -10,7 +10,7 @@
|
||||
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.81 2003/06/25 01:19:47 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.82 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -388,7 +388,7 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname)
|
||||
flags = fcntl(sock, F_GETFL);
|
||||
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||
libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
@@ -435,7 +435,7 @@ pg_krb5_sendauth(char *PQerrormsg, int sock, const char *hostname)
|
||||
|
||||
if (fcntl(sock, F_SETFL, (long) flags))
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
|
||||
@@ -496,11 +496,11 @@ pg_local_sendauth(char *PQerrormsg, PGconn *conn)
|
||||
|
||||
if (sendmsg(conn->sock, &msg, 0) == -1)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||
"pg_local_sendauth: sendmsg: %s\n",
|
||||
pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
"pg_local_sendauth: sendmsg: %s\n",
|
||||
pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
return STATUS_OK;
|
||||
@@ -592,9 +592,9 @@ fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
|
||||
case AUTH_REQ_KRB4:
|
||||
#ifdef KRB4
|
||||
if (pg_krb4_sendauth(PQerrormsg, conn->sock,
|
||||
(struct sockaddr_in *)&conn->laddr.addr,
|
||||
(struct sockaddr_in *)&conn->raddr.addr,
|
||||
hostname) != STATUS_OK)
|
||||
(struct sockaddr_in *) & conn->laddr.addr,
|
||||
(struct sockaddr_in *) & conn->raddr.addr,
|
||||
hostname) != STATUS_OK)
|
||||
{
|
||||
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||
libpq_gettext("Kerberos 4 authentication failed\n"));
|
||||
@@ -610,7 +610,7 @@ fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
|
||||
case AUTH_REQ_KRB5:
|
||||
#ifdef KRB5
|
||||
if (pg_krb5_sendauth(PQerrormsg, conn->sock,
|
||||
hostname) != STATUS_OK)
|
||||
hostname) != STATUS_OK)
|
||||
{
|
||||
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
|
||||
libpq_gettext("Kerberos 5 authentication failed\n"));
|
||||
@@ -743,13 +743,13 @@ fe_getauthname(char *PQerrormsg)
|
||||
if (GetUserName(username, &namesize))
|
||||
name = username;
|
||||
#else
|
||||
char pwdbuf[BUFSIZ];
|
||||
char pwdbuf[BUFSIZ];
|
||||
struct passwd pwdstr;
|
||||
struct passwd *pw = NULL;
|
||||
|
||||
if( pqGetpwuid(geteuid(), &pwdstr,
|
||||
pwdbuf, sizeof(pwdbuf), &pw) == 0 )
|
||||
name = pw->pw_name;
|
||||
if (pqGetpwuid(geteuid(), &pwdstr,
|
||||
pwdbuf, sizeof(pwdbuf), &pw) == 0)
|
||||
name = pw->pw_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.257 2003/08/01 21:27:26 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.258 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
/* For FNCTL_NONBLOCK */
|
||||
#if defined(WIN32) || defined(__BEOS__)
|
||||
long ioctlsocket_ret;
|
||||
long ioctlsocket_ret;
|
||||
#endif
|
||||
|
||||
#define PGPASSFILE ".pgpass"
|
||||
@@ -136,21 +136,21 @@ static const PQconninfoOption PQconninfoOptions[] = {
|
||||
"Backend-Debug-Options", "D", 40},
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
/*
|
||||
* "requiressl" is deprecated, its purpose having been taken over
|
||||
* by "sslmode". It remains for backwards compatibility.
|
||||
* "requiressl" is deprecated, its purpose having been taken over by
|
||||
* "sslmode". It remains for backwards compatibility.
|
||||
*/
|
||||
{"requiressl", "PGREQUIRESSL", "0", NULL,
|
||||
"Require-SSL", "D", 1},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "sslmode" option is allowed even without client SSL support
|
||||
* because the client can still handle SSL modes "disable" and
|
||||
* "allow".
|
||||
* "sslmode" option is allowed even without client SSL support because
|
||||
* the client can still handle SSL modes "disable" and "allow".
|
||||
*/
|
||||
{"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
|
||||
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
|
||||
"SSL-Mode", "", 8}, /* sizeof("disable") == 8 */
|
||||
|
||||
/* Terminating entry --- MUST BE LAST */
|
||||
{NULL, NULL, NULL, NULL,
|
||||
@@ -196,7 +196,7 @@ static int parseServiceInfo(PQconninfoOption *options,
|
||||
PQExpBuffer errorMessage);
|
||||
static char *pwdfMatchesString(char *buf, char *token);
|
||||
static char *PasswordFromFile(char *hostname, char *port, char *dbname,
|
||||
char *username);
|
||||
char *username);
|
||||
|
||||
/*
|
||||
* Connecting to a Database
|
||||
@@ -425,6 +425,7 @@ connectOptions2(PGconn *conn)
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/*
|
||||
* parse dbName to get all additional info in it, if any
|
||||
*/
|
||||
@@ -448,22 +449,24 @@ connectOptions2(PGconn *conn)
|
||||
{
|
||||
conn->status = CONNECTION_BAD;
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("unrecognized sslmode: \"%s\"\n"),
|
||||
libpq_gettext("unrecognized sslmode: \"%s\"\n"),
|
||||
conn->sslmode);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef USE_SSL
|
||||
switch (conn->sslmode[0]) {
|
||||
case 'a': /* "allow" */
|
||||
case 'p': /* "prefer" */
|
||||
switch (conn->sslmode[0])
|
||||
{
|
||||
case 'a': /* "allow" */
|
||||
case 'p': /* "prefer" */
|
||||
|
||||
/*
|
||||
* warn user that an SSL connection will never be
|
||||
* negotiated since SSL was not compiled in?
|
||||
*/
|
||||
break;
|
||||
|
||||
case 'r': /* "require" */
|
||||
case 'r': /* "require" */
|
||||
conn->status = CONNECTION_BAD;
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("sslmode \"%s\" invalid when SSL support is not compiled in\n"),
|
||||
@@ -774,11 +777,11 @@ connectMakeNonblocking(PGconn *conn)
|
||||
{
|
||||
if (FCNTL_NONBLOCK(conn->sock) < 0)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -801,11 +804,11 @@ connectNoDelay(PGconn *conn)
|
||||
(char *) &on,
|
||||
sizeof(on)) < 0)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -822,12 +825,12 @@ connectNoDelay(PGconn *conn)
|
||||
static void
|
||||
connectFailureMessage(PGconn *conn, int errorno)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
if (IS_AF_UNIX(conn->raddr.addr.ss_family))
|
||||
{
|
||||
char service[NI_MAXHOST];
|
||||
char service[NI_MAXHOST];
|
||||
|
||||
getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
|
||||
NULL, 0,
|
||||
@@ -848,7 +851,7 @@ connectFailureMessage(PGconn *conn, int errorno)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
"could not connect to server: %s\n"
|
||||
"\tIs the server running on host \"%s\" and accepting\n"
|
||||
"\tIs the server running on host \"%s\" and accepting\n"
|
||||
"\tTCP/IP connections on port %s?\n"
|
||||
),
|
||||
SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
|
||||
@@ -873,10 +876,10 @@ static int
|
||||
connectDBStart(PGconn *conn)
|
||||
{
|
||||
int portnum;
|
||||
char portstr[128];
|
||||
struct addrinfo *addrs = NULL;
|
||||
struct addrinfo hint;
|
||||
const char *node = NULL;
|
||||
char portstr[128];
|
||||
struct addrinfo *addrs = NULL;
|
||||
struct addrinfo hint;
|
||||
const char *node = NULL;
|
||||
int ret;
|
||||
|
||||
if (!conn)
|
||||
@@ -943,9 +946,9 @@ connectDBStart(PGconn *conn)
|
||||
|
||||
#ifdef USE_SSL
|
||||
/* setup values based on SSL mode */
|
||||
if (conn->sslmode[0] == 'd') /* "disable" */
|
||||
if (conn->sslmode[0] == 'd') /* "disable" */
|
||||
conn->allow_ssl_try = false;
|
||||
else if (conn->sslmode[0] == 'a') /* "allow" */
|
||||
else if (conn->sslmode[0] == 'a') /* "allow" */
|
||||
conn->wait_ssl_try = true;
|
||||
#endif
|
||||
|
||||
@@ -955,15 +958,16 @@ connectDBStart(PGconn *conn)
|
||||
conn->addrlist = addrs;
|
||||
conn->addr_cur = addrs;
|
||||
conn->addrlist_family = hint.ai_family;
|
||||
conn->pversion = PG_PROTOCOL(3,0);
|
||||
conn->pversion = PG_PROTOCOL(3, 0);
|
||||
conn->status = CONNECTION_NEEDED;
|
||||
|
||||
/*
|
||||
* The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
|
||||
* so that it can easily be re-executed if needed again during the
|
||||
* asynchronous startup process. However, we must run it once here,
|
||||
* because callers expect a success return from this routine to mean
|
||||
* that we are in PGRES_POLLING_WRITING connection state.
|
||||
* The code for processing CONNECTION_NEEDED state is in
|
||||
* PQconnectPoll(), so that it can easily be re-executed if needed
|
||||
* again during the asynchronous startup process. However, we must
|
||||
* run it once here, because callers expect a success return from this
|
||||
* routine to mean that we are in PGRES_POLLING_WRITING connection
|
||||
* state.
|
||||
*/
|
||||
if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
|
||||
return 1;
|
||||
@@ -1154,8 +1158,8 @@ keep_going: /* We will come back to here until there
|
||||
* Try to initiate a connection to one of the addresses
|
||||
* returned by getaddrinfo_all(). conn->addr_cur is the
|
||||
* next one to try. We fail when we run out of addresses
|
||||
* (reporting the error returned for the *last* alternative,
|
||||
* which may not be what users expect :-().
|
||||
* (reporting the error returned for the *last*
|
||||
* alternative, which may not be what users expect :-().
|
||||
*/
|
||||
while (conn->addr_cur != NULL)
|
||||
{
|
||||
@@ -1171,8 +1175,8 @@ keep_going: /* We will come back to here until there
|
||||
if (conn->sock < 0)
|
||||
{
|
||||
/*
|
||||
* ignore socket() failure if we have more addresses
|
||||
* to try
|
||||
* ignore socket() failure if we have more
|
||||
* addresses to try
|
||||
*/
|
||||
if (addr_cur->ai_next != NULL)
|
||||
{
|
||||
@@ -1180,14 +1184,15 @@ keep_going: /* We will come back to here until there
|
||||
continue;
|
||||
}
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not create socket: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
libpq_gettext("could not create socket: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select socket options: no delay of outgoing data for
|
||||
* TCP sockets, and nonblock mode. Fail if this fails.
|
||||
* Select socket options: no delay of outgoing data
|
||||
* for TCP sockets, and nonblock mode. Fail if this
|
||||
* fails.
|
||||
*/
|
||||
if (!IS_AF_UNIX(addr_cur->ai_family))
|
||||
{
|
||||
@@ -1206,11 +1211,13 @@ keep_going: /* We will come back to here until there
|
||||
conn->addr_cur = addr_cur->ai_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start/make connection. This should not block, since
|
||||
* we are in nonblock mode. If it does, well, too bad.
|
||||
* Start/make connection. This should not block,
|
||||
* since we are in nonblock mode. If it does, well,
|
||||
* too bad.
|
||||
*/
|
||||
retry_connect:
|
||||
retry_connect:
|
||||
if (connect(conn->sock, addr_cur->ai_addr,
|
||||
addr_cur->ai_addrlen) < 0)
|
||||
{
|
||||
@@ -1235,18 +1242,19 @@ retry_connect:
|
||||
{
|
||||
/*
|
||||
* Hm, we're connected already --- seems the
|
||||
* "nonblock connection" wasn't. Advance the state
|
||||
* machine and go do the next stuff.
|
||||
* "nonblock connection" wasn't. Advance the
|
||||
* state machine and go do the next stuff.
|
||||
*/
|
||||
conn->status = CONNECTION_STARTED;
|
||||
goto keep_going;
|
||||
}
|
||||
|
||||
/*
|
||||
* This connection failed --- set up error report,
|
||||
* then close socket (do it this way in case close()
|
||||
* affects the value of errno...). We will ignore the
|
||||
* connect() failure and keep going if there are
|
||||
* more addresses.
|
||||
* affects the value of errno...). We will ignore the
|
||||
* connect() failure and keep going if there are more
|
||||
* addresses.
|
||||
*/
|
||||
connectFailureMessage(conn, SOCK_ERRNO);
|
||||
if (conn->sock >= 0)
|
||||
@@ -1254,11 +1262,12 @@ retry_connect:
|
||||
closesocket(conn->sock);
|
||||
conn->sock = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try the next address, if any.
|
||||
*/
|
||||
conn->addr_cur = addr_cur->ai_next;
|
||||
} /* loop over addresses */
|
||||
} /* loop over addresses */
|
||||
|
||||
/*
|
||||
* Ooops, no more addresses. An appropriate error message
|
||||
@@ -1270,7 +1279,7 @@ retry_connect:
|
||||
case CONNECTION_STARTED:
|
||||
{
|
||||
int optval;
|
||||
ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
|
||||
ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
|
||||
|
||||
/*
|
||||
* Write ready, since we've made it here, so the
|
||||
@@ -1287,7 +1296,7 @@ retry_connect:
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not get socket error status: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
goto error_return;
|
||||
}
|
||||
else if (optval != 0)
|
||||
@@ -1298,9 +1307,11 @@ retry_connect:
|
||||
* friendly error message.
|
||||
*/
|
||||
connectFailureMessage(conn, optval);
|
||||
|
||||
/*
|
||||
* If more addresses remain, keep trying, just as in
|
||||
* the case where connect() returned failure immediately.
|
||||
* the case where connect() returned failure
|
||||
* immediately.
|
||||
*/
|
||||
if (conn->addr_cur->ai_next != NULL)
|
||||
{
|
||||
@@ -1318,13 +1329,13 @@ retry_connect:
|
||||
|
||||
/* Fill in the client address */
|
||||
conn->laddr.salen = sizeof(conn->laddr.addr);
|
||||
if (getsockname(conn->sock,
|
||||
(struct sockaddr *)&conn->laddr.addr,
|
||||
&conn->laddr.salen) < 0)
|
||||
if (getsockname(conn->sock,
|
||||
(struct sockaddr *) & conn->laddr.addr,
|
||||
&conn->laddr.salen) < 0)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not get client address from socket: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
libpq_gettext("could not get client address from socket: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
@@ -1337,13 +1348,15 @@ retry_connect:
|
||||
|
||||
case CONNECTION_MADE:
|
||||
{
|
||||
char *startpacket;
|
||||
int packetlen;
|
||||
char *startpacket;
|
||||
int packetlen;
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
/*
|
||||
* If SSL is enabled and we haven't already got it running,
|
||||
* request it instead of sending the startup message.
|
||||
* If SSL is enabled and we haven't already got it
|
||||
* running, request it instead of sending the startup
|
||||
* message.
|
||||
*/
|
||||
if (IS_AF_UNIX(conn->raddr.addr.ss_family))
|
||||
{
|
||||
@@ -1358,32 +1371,33 @@ retry_connect:
|
||||
/*
|
||||
* Send the SSL request packet.
|
||||
*
|
||||
* Theoretically, this could block, but it really shouldn't
|
||||
* since we only got here if the socket is write-ready.
|
||||
* Theoretically, this could block, but it really
|
||||
* shouldn't since we only got here if the socket is
|
||||
* write-ready.
|
||||
*/
|
||||
pv = htonl(NEGOTIATE_SSL_CODE);
|
||||
if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not send SSL negotiation packet: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
goto error_return;
|
||||
}
|
||||
/* Ok, wait for response */
|
||||
conn->status = CONNECTION_SSL_STARTUP;
|
||||
return PGRES_POLLING_READING;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
#endif /* USE_SSL */
|
||||
|
||||
/*
|
||||
* Build the startup packet.
|
||||
*/
|
||||
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
|
||||
startpacket = pqBuildStartupPacket3(conn, &packetlen,
|
||||
EnvironmentOptions);
|
||||
EnvironmentOptions);
|
||||
else
|
||||
startpacket = pqBuildStartupPacket2(conn, &packetlen,
|
||||
EnvironmentOptions);
|
||||
EnvironmentOptions);
|
||||
if (!startpacket)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
@@ -1401,7 +1415,7 @@ retry_connect:
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not send startup packet: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
free(startpacket);
|
||||
goto error_return;
|
||||
}
|
||||
@@ -1413,8 +1427,8 @@ retry_connect:
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle SSL negotiation: wait for postmaster
|
||||
* messages and respond as necessary.
|
||||
* Handle SSL negotiation: wait for postmaster messages and
|
||||
* respond as necessary.
|
||||
*/
|
||||
case CONNECTION_SSL_STARTUP:
|
||||
{
|
||||
@@ -1422,8 +1436,8 @@ retry_connect:
|
||||
PostgresPollingStatusType pollres;
|
||||
|
||||
/*
|
||||
* On first time through, get the postmaster's response
|
||||
* to our SSL negotiation packet. Be careful to read only
|
||||
* On first time through, get the postmaster's response to
|
||||
* our SSL negotiation packet. Be careful to read only
|
||||
* one byte (if there's more, it could be SSL data).
|
||||
*/
|
||||
if (conn->ssl == NULL)
|
||||
@@ -1431,7 +1445,7 @@ retry_connect:
|
||||
char SSLok;
|
||||
int nread;
|
||||
|
||||
retry_ssl_read:
|
||||
retry_ssl_read:
|
||||
nread = recv(conn->sock, &SSLok, 1, 0);
|
||||
if (nread < 0)
|
||||
{
|
||||
@@ -1441,7 +1455,7 @@ retry_ssl_read:
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
goto error_return;
|
||||
}
|
||||
if (nread == 0)
|
||||
@@ -1455,7 +1469,7 @@ retry_ssl_read:
|
||||
}
|
||||
else if (SSLok == 'N')
|
||||
{
|
||||
if (conn->sslmode[0] == 'r') /* "require" */
|
||||
if (conn->sslmode[0] == 'r') /* "require" */
|
||||
{
|
||||
/* Require SSL, but server does not want it */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
@@ -1472,7 +1486,7 @@ retry_ssl_read:
|
||||
/* Received error - probably protocol mismatch */
|
||||
if (conn->Pfdebug)
|
||||
fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n");
|
||||
if (conn->sslmode[0] == 'r') /* "require" */
|
||||
if (conn->sslmode[0] == 'r') /* "require" */
|
||||
{
|
||||
/* Require SSL, but server is too old */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
@@ -1482,7 +1496,7 @@ retry_ssl_read:
|
||||
/* Otherwise, try again without SSL */
|
||||
conn->allow_ssl_try = false;
|
||||
/* Assume it ain't gonna handle protocol 3, either */
|
||||
conn->pversion = PG_PROTOCOL(2,0);
|
||||
conn->pversion = PG_PROTOCOL(2, 0);
|
||||
/* Must drop the old connection */
|
||||
closesocket(conn->sock);
|
||||
conn->sock = -1;
|
||||
@@ -1497,6 +1511,7 @@ retry_ssl_read:
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin or continue the SSL negotiation process.
|
||||
*/
|
||||
@@ -1508,10 +1523,10 @@ retry_ssl_read:
|
||||
return PGRES_POLLING_WRITING;
|
||||
}
|
||||
return pollres;
|
||||
#else /* !USE_SSL */
|
||||
#else /* !USE_SSL */
|
||||
/* can't get here */
|
||||
goto error_return;
|
||||
#endif /* USE_SSL */
|
||||
#endif /* USE_SSL */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1549,7 +1564,7 @@ retry_ssl_read:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
"expected authentication request from "
|
||||
"server, but received %c\n"),
|
||||
"server, but received %c\n"),
|
||||
beresp);
|
||||
goto error_return;
|
||||
}
|
||||
@@ -1572,16 +1587,16 @@ retry_ssl_read:
|
||||
/*
|
||||
* Try to validate message length before using it.
|
||||
* Authentication requests can't be very large. Errors
|
||||
* can be a little larger, but not huge. If we see a large
|
||||
* apparent length in an error, it means we're really talking
|
||||
* to a pre-3.0-protocol server; cope.
|
||||
* can be a little larger, but not huge. If we see a
|
||||
* large apparent length in an error, it means we're
|
||||
* really talking to a pre-3.0-protocol server; cope.
|
||||
*/
|
||||
if (beresp == 'R' && (msgLength < 8 || msgLength > 100))
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
"expected authentication request from "
|
||||
"server, but received %c\n"),
|
||||
"server, but received %c\n"),
|
||||
beresp);
|
||||
goto error_return;
|
||||
}
|
||||
@@ -1589,7 +1604,7 @@ retry_ssl_read:
|
||||
if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
|
||||
{
|
||||
/* Handle error from a pre-3.0 server */
|
||||
conn->inCursor = conn->inStart + 1; /* reread data */
|
||||
conn->inCursor = conn->inStart + 1; /* reread data */
|
||||
if (pqGets(&conn->errorMessage, conn))
|
||||
{
|
||||
/* We'll come back when there is more data */
|
||||
@@ -1611,7 +1626,7 @@ retry_ssl_read:
|
||||
*/
|
||||
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
|
||||
{
|
||||
conn->pversion = PG_PROTOCOL(2,0);
|
||||
conn->pversion = PG_PROTOCOL(2, 0);
|
||||
/* Must drop the old connection */
|
||||
pqsecure_close(conn);
|
||||
closesocket(conn->sock);
|
||||
@@ -1626,16 +1641,16 @@ retry_ssl_read:
|
||||
/*
|
||||
* Can't process if message body isn't all here yet.
|
||||
*
|
||||
* (In protocol 2.0 case, we are assuming messages carry
|
||||
* at least 4 bytes of data.)
|
||||
* (In protocol 2.0 case, we are assuming messages carry at
|
||||
* least 4 bytes of data.)
|
||||
*/
|
||||
msgLength -= 4;
|
||||
avail = conn->inEnd - conn->inCursor;
|
||||
if (avail < msgLength)
|
||||
{
|
||||
/*
|
||||
* Before returning, try to enlarge the input buffer if
|
||||
* needed to hold the whole message; see notes in
|
||||
* Before returning, try to enlarge the input buffer
|
||||
* if needed to hold the whole message; see notes in
|
||||
* pqParseInput3.
|
||||
*/
|
||||
if (pqCheckInBufferSpace(conn->inCursor + msgLength, conn))
|
||||
@@ -1667,9 +1682,11 @@ retry_ssl_read:
|
||||
conn->inStart = conn->inCursor;
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
/*
|
||||
* if sslmode is "allow" and we haven't tried an SSL
|
||||
* connection already, then retry with an SSL connection
|
||||
* connection already, then retry with an SSL
|
||||
* connection
|
||||
*/
|
||||
if (conn->sslmode[0] == 'a' /* "allow" */
|
||||
&& conn->ssl == NULL
|
||||
@@ -1691,8 +1708,8 @@ retry_ssl_read:
|
||||
*/
|
||||
if (conn->sslmode[0] == 'p' /* "prefer" */
|
||||
&& conn->ssl
|
||||
&& conn->allow_ssl_try /* redundant? */
|
||||
&& !conn->wait_ssl_try) /* redundant? */
|
||||
&& conn->allow_ssl_try /* redundant? */
|
||||
&& !conn->wait_ssl_try) /* redundant? */
|
||||
{
|
||||
/* only retry once */
|
||||
conn->allow_ssl_try = false;
|
||||
@@ -1797,8 +1814,8 @@ retry_ssl_read:
|
||||
* allowed by the protocol, as are ParameterStatus and
|
||||
* BackendKeyData messages.) Easiest way to handle this is
|
||||
* to let PQgetResult() read the messages. We just have to
|
||||
* fake it out about the state of the connection, by setting
|
||||
* asyncStatus = PGASYNC_BUSY (done above).
|
||||
* fake it out about the state of the connection, by
|
||||
* setting asyncStatus = PGASYNC_BUSY (done above).
|
||||
*/
|
||||
|
||||
if (PQisBusy(conn))
|
||||
@@ -1852,10 +1869,11 @@ retry_ssl_read:
|
||||
case CONNECTION_SETENV:
|
||||
|
||||
/*
|
||||
* Do post-connection housekeeping (only needed in protocol 2.0).
|
||||
* Do post-connection housekeeping (only needed in protocol
|
||||
* 2.0).
|
||||
*
|
||||
* We pretend that the connection is OK for the duration of
|
||||
* these queries.
|
||||
* We pretend that the connection is OK for the duration of these
|
||||
* queries.
|
||||
*/
|
||||
conn->status = CONNECTION_OK;
|
||||
|
||||
@@ -1917,10 +1935,10 @@ makeEmptyPGconn(void)
|
||||
|
||||
#ifdef WIN32
|
||||
/* needed to use the static libpq under windows as well */
|
||||
WSADATA wsaData;
|
||||
WSADATA wsaData;
|
||||
|
||||
if (WSAStartup(MAKEWORD(1, 1), &wsaData))
|
||||
return (PGconn*) NULL;
|
||||
return (PGconn *) NULL;
|
||||
WSASetLastError(0);
|
||||
#endif
|
||||
|
||||
@@ -1947,8 +1965,8 @@ makeEmptyPGconn(void)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We try to send at least 8K at a time, which is the usual size
|
||||
* of pipe buffers on Unix systems. That way, when we are sending a
|
||||
* We try to send at least 8K at a time, which is the usual size of
|
||||
* pipe buffers on Unix systems. That way, when we are sending a
|
||||
* large amount of data, we avoid incurring extra kernel context swaps
|
||||
* for partial bufferloads. The output buffer is initially made 16K
|
||||
* in size, and we try to dump it after accumulating 8K.
|
||||
@@ -2211,8 +2229,8 @@ PQrequestCancel(PGconn *conn)
|
||||
goto cancel_errReturn;
|
||||
}
|
||||
retry3:
|
||||
if (connect(tmpsock, (struct sockaddr *)&conn->raddr.addr,
|
||||
conn->raddr.salen) < 0)
|
||||
if (connect(tmpsock, (struct sockaddr *) & conn->raddr.addr,
|
||||
conn->raddr.salen) < 0)
|
||||
{
|
||||
if (SOCK_ERRNO == EINTR)
|
||||
/* Interrupted system call - we'll just try again */
|
||||
@@ -2404,7 +2422,7 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
|
||||
|
||||
key = line;
|
||||
val = strchr(line, '=');
|
||||
if( val == NULL )
|
||||
if (val == NULL)
|
||||
{
|
||||
printfPQExpBuffer(errorMessage,
|
||||
"ERROR: syntax error in service file '%s', line %d\n",
|
||||
@@ -2416,8 +2434,8 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
|
||||
*val++ = '\0';
|
||||
|
||||
/*
|
||||
* If not already set, set the database name to the
|
||||
* name of the service
|
||||
* If not already set, set the database name to the
|
||||
* name of the service
|
||||
*/
|
||||
for (i = 0; options[i].keyword; i++)
|
||||
{
|
||||
@@ -2641,8 +2659,8 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage)
|
||||
free(buf);
|
||||
|
||||
/*
|
||||
* If there's a service spec, use it to obtain any not-explicitly-given
|
||||
* parameters.
|
||||
* If there's a service spec, use it to obtain any
|
||||
* not-explicitly-given parameters.
|
||||
*/
|
||||
if (parseServiceInfo(options, errorMessage))
|
||||
{
|
||||
@@ -2901,7 +2919,7 @@ PQsetClientEncoding(PGconn *conn, const char *encoding)
|
||||
PGVerbosity
|
||||
PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
|
||||
{
|
||||
PGVerbosity old;
|
||||
PGVerbosity old;
|
||||
|
||||
if (!conn)
|
||||
return PQERRORS_DEFAULT;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.141 2003/06/28 00:06:01 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.142 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -449,7 +449,7 @@ pqPrepareAsyncResult(PGconn *conn)
|
||||
* a trailing newline, and should not be more than one line).
|
||||
*/
|
||||
void
|
||||
pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt, ...)
|
||||
pqInternalNotice(const PGNoticeHooks * hooks, const char *fmt,...)
|
||||
{
|
||||
char msgBuf[1024];
|
||||
va_list args;
|
||||
@@ -462,22 +462,25 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt, ...)
|
||||
va_start(args, fmt);
|
||||
vsnprintf(msgBuf, sizeof(msgBuf), libpq_gettext(fmt), args);
|
||||
va_end(args);
|
||||
msgBuf[sizeof(msgBuf)-1] = '\0'; /* make real sure it's terminated */
|
||||
msgBuf[sizeof(msgBuf) - 1] = '\0'; /* make real sure it's terminated */
|
||||
|
||||
/* Make a PGresult to pass to the notice receiver */
|
||||
res = PQmakeEmptyPGresult(NULL, PGRES_NONFATAL_ERROR);
|
||||
res->noticeHooks = *hooks;
|
||||
|
||||
/*
|
||||
* Set up fields of notice.
|
||||
*/
|
||||
pqSaveMessageField(res, 'M', msgBuf);
|
||||
pqSaveMessageField(res, 'S', libpq_gettext("NOTICE"));
|
||||
/* XXX should provide a SQLSTATE too? */
|
||||
|
||||
/*
|
||||
* Result text is always just the primary message + newline.
|
||||
*/
|
||||
res->errMsg = (char *) pqResultAlloc(res, strlen(msgBuf) + 2, FALSE);
|
||||
sprintf(res->errMsg, "%s\n", msgBuf);
|
||||
|
||||
/*
|
||||
* Pass to receiver, then free it.
|
||||
*/
|
||||
@@ -491,7 +494,7 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt, ...)
|
||||
* Returns TRUE if OK, FALSE if not enough memory to add the row
|
||||
*/
|
||||
int
|
||||
pqAddTuple(PGresult *res, PGresAttValue *tup)
|
||||
pqAddTuple(PGresult *res, PGresAttValue * tup)
|
||||
{
|
||||
if (res->ntups >= res->tupArrSize)
|
||||
{
|
||||
@@ -575,11 +578,12 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store new info as a single malloc block
|
||||
*/
|
||||
pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
|
||||
strlen(name) + strlen(value) + 2);
|
||||
strlen(name) + strlen(value) + 2);
|
||||
if (pstatus)
|
||||
{
|
||||
char *ptr;
|
||||
@@ -593,6 +597,7 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
|
||||
pstatus->next = conn->pstatus;
|
||||
conn->pstatus = pstatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special hacks: remember client_encoding as a numeric value, and
|
||||
* remember at least the first few bytes of server version.
|
||||
@@ -635,8 +640,8 @@ PQsendQuery(PGconn *conn, const char *query)
|
||||
|
||||
/*
|
||||
* Give the data a push. In nonblock mode, don't complain if we're
|
||||
* unable to send it all; PQgetResult() will do any additional flushing
|
||||
* needed.
|
||||
* unable to send it all; PQgetResult() will do any additional
|
||||
* flushing needed.
|
||||
*/
|
||||
if (pqFlush(conn) < 0)
|
||||
{
|
||||
@@ -658,7 +663,7 @@ PQsendQueryParams(PGconn *conn,
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char * const *paramValues,
|
||||
const char *const * paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat)
|
||||
@@ -672,7 +677,7 @@ PQsendQueryParams(PGconn *conn,
|
||||
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("function requires at least 3.0 protocol\n"));
|
||||
libpq_gettext("function requires at least 3.0 protocol\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -737,7 +742,7 @@ PQsendQueryParams(PGconn *conn,
|
||||
{
|
||||
if (paramValues && paramValues[i])
|
||||
{
|
||||
int nbytes;
|
||||
int nbytes;
|
||||
|
||||
if (paramFormats && paramFormats[i] != 0)
|
||||
{
|
||||
@@ -787,8 +792,8 @@ PQsendQueryParams(PGconn *conn,
|
||||
|
||||
/*
|
||||
* Give the data a push. In nonblock mode, don't complain if we're
|
||||
* unable to send it all; PQgetResult() will do any additional flushing
|
||||
* needed.
|
||||
* unable to send it all; PQgetResult() will do any additional
|
||||
* flushing needed.
|
||||
*/
|
||||
if (pqFlush(conn) < 0)
|
||||
goto sendFailed;
|
||||
@@ -875,9 +880,9 @@ PQconsumeInput(PGconn *conn)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* for non-blocking connections try to flush the send-queue,
|
||||
* otherwise we may never get a response for something that may
|
||||
* not have already been sent because it's in our write buffer!
|
||||
* for non-blocking connections try to flush the send-queue, otherwise
|
||||
* we may never get a response for something that may not have already
|
||||
* been sent because it's in our write buffer!
|
||||
*/
|
||||
if (pqIsnonblocking(conn))
|
||||
{
|
||||
@@ -952,11 +957,11 @@ PQgetResult(PGconn *conn)
|
||||
/* If not ready to return something, block until we are. */
|
||||
while (conn->asyncStatus == PGASYNC_BUSY)
|
||||
{
|
||||
int flushResult;
|
||||
int flushResult;
|
||||
|
||||
/*
|
||||
* If data remains unsent, send it. Else we might be waiting
|
||||
* for the result of a command the backend hasn't even got yet.
|
||||
* If data remains unsent, send it. Else we might be waiting for
|
||||
* the result of a command the backend hasn't even got yet.
|
||||
*/
|
||||
while ((flushResult = pqFlush(conn)) > 0)
|
||||
{
|
||||
@@ -1051,7 +1056,7 @@ PQexecParams(PGconn *conn,
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char * const *paramValues,
|
||||
const char *const * paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat)
|
||||
@@ -1089,7 +1094,7 @@ PQexecStart(PGconn *conn)
|
||||
{
|
||||
/* In protocol 3, we can get out of a COPY IN state */
|
||||
if (PQputCopyEnd(conn,
|
||||
libpq_gettext("COPY terminated by new PQexec")) < 0)
|
||||
libpq_gettext("COPY terminated by new PQexec")) < 0)
|
||||
{
|
||||
PQclear(result);
|
||||
return false;
|
||||
@@ -1101,7 +1106,7 @@ PQexecStart(PGconn *conn)
|
||||
/* In older protocols we have to punt */
|
||||
PQclear(result);
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("COPY IN state must be terminated first\n"));
|
||||
libpq_gettext("COPY IN state must be terminated first\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1122,7 +1127,7 @@ PQexecStart(PGconn *conn)
|
||||
/* In older protocols we have to punt */
|
||||
PQclear(result);
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("COPY OUT state must be terminated first\n"));
|
||||
libpq_gettext("COPY OUT state must be terminated first\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1161,7 +1166,11 @@ PQexecFinish(PGconn *conn)
|
||||
pqCatenateResultError(lastResult, result->errMsg);
|
||||
PQclear(result);
|
||||
result = lastResult;
|
||||
/* Make sure PQerrorMessage agrees with concatenated result */
|
||||
|
||||
/*
|
||||
* Make sure PQerrorMessage agrees with concatenated
|
||||
* result
|
||||
*/
|
||||
resetPQExpBuffer(&conn->errorMessage);
|
||||
appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
|
||||
}
|
||||
@@ -1229,8 +1238,8 @@ PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
|
||||
{
|
||||
/*
|
||||
* Try to flush any previously sent data in preference to growing
|
||||
* the output buffer. If we can't enlarge the buffer enough to hold
|
||||
* the data, return 0 in the nonblock case, else hard error.
|
||||
* the output buffer. If we can't enlarge the buffer enough to
|
||||
* hold the data, return 0 in the nonblock case, else hard error.
|
||||
* (For simplicity, always assume 5 bytes of overhead even in
|
||||
* protocol 2.0 case.)
|
||||
*/
|
||||
@@ -1279,6 +1288,7 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
|
||||
libpq_gettext("no COPY in progress\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the COPY END indicator. This is simple enough that we don't
|
||||
* bother delegating it to the fe-protocol files.
|
||||
@@ -1307,7 +1317,7 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
|
||||
{
|
||||
/* Ooops, no way to do this in 2.0 */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("function requires at least 3.0 protocol\n"));
|
||||
libpq_gettext("function requires at least 3.0 protocol\n"));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
@@ -1476,7 +1486,7 @@ PQputnbytes(PGconn *conn, const char *buffer, int nbytes)
|
||||
* the application must call this routine to finish the command protocol.
|
||||
*
|
||||
* When using 3.0 protocol this is deprecated; it's cleaner to use PQgetResult
|
||||
* to get the transfer status. Note however that when using 2.0 protocol,
|
||||
* to get the transfer status. Note however that when using 2.0 protocol,
|
||||
* recovering from a copy failure often requires a PQreset. PQendcopy will
|
||||
* take care of that, PQgetResult won't.
|
||||
*
|
||||
@@ -1861,7 +1871,7 @@ PQoidValue(const PGresult *res)
|
||||
char *
|
||||
PQcmdTuples(PGresult *res)
|
||||
{
|
||||
char *p;
|
||||
char *p;
|
||||
|
||||
if (!res)
|
||||
return "";
|
||||
@@ -1994,7 +2004,8 @@ PQflush(PGconn *conn)
|
||||
* Needed mostly by Win32, unless multithreaded DLL (/MD in VC6)
|
||||
* Used for freeing memory from PQescapeByte()a/PQunescapeBytea()
|
||||
*/
|
||||
void PQfreemem(void *ptr)
|
||||
void
|
||||
PQfreemem(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
@@ -2004,11 +2015,11 @@ void PQfreemem(void *ptr)
|
||||
*
|
||||
* This function is here only for binary backward compatibility.
|
||||
* New code should use PQfreemem(). A macro will automatically map
|
||||
* calls to PQfreemem. It should be removed in the future. bjm 2003-03-24
|
||||
* calls to PQfreemem. It should be removed in the future. bjm 2003-03-24
|
||||
*/
|
||||
|
||||
#undef PQfreeNotify
|
||||
void PQfreeNotify(PGnotify *notify);
|
||||
void PQfreeNotify(PGnotify *notify);
|
||||
|
||||
void
|
||||
PQfreeNotify(PGnotify *notify)
|
||||
@@ -2151,26 +2162,30 @@ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen)
|
||||
* argument to the function free(3). It is the reverse of PQescapeBytea.
|
||||
*
|
||||
* The following transformations are made:
|
||||
* \' == ASCII 39 == '
|
||||
* \\ == ASCII 92 == \
|
||||
* \' == ASCII 39 == '
|
||||
* \\ == ASCII 92 == \
|
||||
* \ooo == a byte whose value = ooo (ooo is an octal number)
|
||||
* \x == x (x is any character not matched by the above transformations)
|
||||
* \x == x (x is any character not matched by the above transformations)
|
||||
*
|
||||
*/
|
||||
unsigned char *
|
||||
PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
||||
{
|
||||
size_t strtextlen, buflen;
|
||||
unsigned char *buffer, *tmpbuf;
|
||||
int i, j, byte;
|
||||
size_t strtextlen,
|
||||
buflen;
|
||||
unsigned char *buffer,
|
||||
*tmpbuf;
|
||||
int i,
|
||||
j,
|
||||
byte;
|
||||
|
||||
if (strtext == NULL) {
|
||||
if (strtext == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strtextlen = strlen(strtext); /* will shrink, also we discover if
|
||||
* strtext isn't NULL terminated */
|
||||
buffer = (unsigned char *)malloc(strtextlen);
|
||||
strtextlen = strlen(strtext); /* will shrink, also we discover
|
||||
* if strtext isn't NULL
|
||||
* terminated */
|
||||
buffer = (unsigned char *) malloc(strtextlen);
|
||||
if (buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -2184,9 +2199,9 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
||||
buffer[j++] = strtext[i++];
|
||||
else
|
||||
{
|
||||
if ((isdigit(strtext[i])) &&
|
||||
(isdigit(strtext[i+1])) &&
|
||||
(isdigit(strtext[i+2])))
|
||||
if ((isdigit(strtext[i])) &&
|
||||
(isdigit(strtext[i + 1])) &&
|
||||
(isdigit(strtext[i + 2])))
|
||||
{
|
||||
byte = VAL(strtext[i++]);
|
||||
byte = (byte << 3) + VAL(strtext[i++]);
|
||||
@@ -2199,7 +2214,8 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
||||
buffer[j++] = strtext[i++];
|
||||
}
|
||||
}
|
||||
buflen = j; /* buflen is the length of the unquoted data */
|
||||
buflen = j; /* buflen is the length of the unquoted
|
||||
* data */
|
||||
tmpbuf = realloc(buffer, buflen);
|
||||
|
||||
if (!tmpbuf)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.42 2003/06/14 17:49:54 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.43 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -396,10 +396,11 @@ lo_import(PGconn *conn, const char *filename)
|
||||
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
|
||||
if (fd < 0)
|
||||
{ /* error */
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not open file \"%s\": %s\n"),
|
||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
@@ -480,10 +481,11 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
|
||||
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
|
||||
if (fd < 0)
|
||||
{ /* error */
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not open file \"%s\": %s\n"),
|
||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
(void) lo_close(conn, lobj);
|
||||
return -1;
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.98 2003/06/23 19:20:25 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.99 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -64,8 +64,8 @@
|
||||
|
||||
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
|
||||
static int pqSendSome(PGconn *conn, int len);
|
||||
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
|
||||
time_t end_time);
|
||||
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
|
||||
time_t end_time);
|
||||
static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
|
||||
break;
|
||||
default:
|
||||
pqInternalNotice(&conn->noticeHooks,
|
||||
"integer of size %lu not supported by pqGetInt",
|
||||
"integer of size %lu not supported by pqGetInt",
|
||||
(unsigned long) bytes);
|
||||
return EOF;
|
||||
}
|
||||
@@ -261,7 +261,7 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
|
||||
break;
|
||||
default:
|
||||
pqInternalNotice(&conn->noticeHooks,
|
||||
"integer of size %lu not supported by pqPutInt",
|
||||
"integer of size %lu not supported by pqPutInt",
|
||||
(unsigned long) bytes);
|
||||
return EOF;
|
||||
}
|
||||
@@ -286,14 +286,16 @@ pqCheckOutBufferSpace(int bytes_needed, PGconn *conn)
|
||||
|
||||
if (bytes_needed <= newsize)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we need to enlarge the buffer, we first try to double it in size;
|
||||
* if that doesn't work, enlarge in multiples of 8K. This avoids
|
||||
* thrashing the malloc pool by repeated small enlargements.
|
||||
* If we need to enlarge the buffer, we first try to double it in
|
||||
* size; if that doesn't work, enlarge in multiples of 8K. This
|
||||
* avoids thrashing the malloc pool by repeated small enlargements.
|
||||
*
|
||||
* Note: tests for newsize > 0 are to catch integer overflow.
|
||||
*/
|
||||
do {
|
||||
do
|
||||
{
|
||||
newsize *= 2;
|
||||
} while (bytes_needed > newsize && newsize > 0);
|
||||
|
||||
@@ -310,7 +312,8 @@ pqCheckOutBufferSpace(int bytes_needed, PGconn *conn)
|
||||
}
|
||||
|
||||
newsize = conn->outBufSize;
|
||||
do {
|
||||
do
|
||||
{
|
||||
newsize += 8192;
|
||||
} while (bytes_needed > newsize && newsize > 0);
|
||||
|
||||
@@ -346,14 +349,16 @@ pqCheckInBufferSpace(int bytes_needed, PGconn *conn)
|
||||
|
||||
if (bytes_needed <= newsize)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we need to enlarge the buffer, we first try to double it in size;
|
||||
* if that doesn't work, enlarge in multiples of 8K. This avoids
|
||||
* thrashing the malloc pool by repeated small enlargements.
|
||||
* If we need to enlarge the buffer, we first try to double it in
|
||||
* size; if that doesn't work, enlarge in multiples of 8K. This
|
||||
* avoids thrashing the malloc pool by repeated small enlargements.
|
||||
*
|
||||
* Note: tests for newsize > 0 are to catch integer overflow.
|
||||
*/
|
||||
do {
|
||||
do
|
||||
{
|
||||
newsize *= 2;
|
||||
} while (bytes_needed > newsize && newsize > 0);
|
||||
|
||||
@@ -370,7 +375,8 @@ pqCheckInBufferSpace(int bytes_needed, PGconn *conn)
|
||||
}
|
||||
|
||||
newsize = conn->inBufSize;
|
||||
do {
|
||||
do
|
||||
{
|
||||
newsize += 8192;
|
||||
} while (bytes_needed > newsize && newsize > 0);
|
||||
|
||||
@@ -435,9 +441,7 @@ pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
|
||||
endPos += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
lenPos = -1;
|
||||
}
|
||||
|
||||
/* make sure there is room for message header */
|
||||
if (pqCheckOutBufferSpace(endPos, conn))
|
||||
@@ -506,7 +510,7 @@ pqPutMsgEnd(PGconn *conn)
|
||||
|
||||
if (conn->outCount >= 8192)
|
||||
{
|
||||
int toSend = conn->outCount - (conn->outCount % 8192);
|
||||
int toSend = conn->outCount - (conn->outCount % 8192);
|
||||
|
||||
if (pqSendSome(conn, toSend) < 0)
|
||||
return EOF;
|
||||
@@ -532,7 +536,7 @@ pqReadData(PGconn *conn)
|
||||
{
|
||||
int someread = 0;
|
||||
int nread;
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
if (conn->sock < 0)
|
||||
{
|
||||
@@ -572,7 +576,8 @@ pqReadData(PGconn *conn)
|
||||
if (pqCheckInBufferSpace(conn->inEnd + 8192, conn))
|
||||
{
|
||||
/*
|
||||
* We don't insist that the enlarge worked, but we need some room
|
||||
* We don't insist that the enlarge worked, but we need some
|
||||
* room
|
||||
*/
|
||||
if (conn->inBufSize - conn->inEnd < 100)
|
||||
return -1; /* errorMessage already set */
|
||||
@@ -603,7 +608,7 @@ retry3:
|
||||
#endif
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not receive data from server: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
return -1;
|
||||
}
|
||||
if (nread > 0)
|
||||
@@ -683,7 +688,7 @@ retry4:
|
||||
#endif
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not receive data from server: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
return -1;
|
||||
}
|
||||
if (nread > 0)
|
||||
@@ -737,15 +742,15 @@ pqSendSome(PGconn *conn, int len)
|
||||
while (len > 0)
|
||||
{
|
||||
int sent;
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
sent = pqsecure_write(conn, ptr, len);
|
||||
|
||||
if (sent < 0)
|
||||
{
|
||||
/*
|
||||
* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble. If it's
|
||||
* EPIPE or ECONNRESET, assume we've lost the backend
|
||||
* Anything except EAGAIN/EWOULDBLOCK/EINTR is trouble. If
|
||||
* it's EPIPE or ECONNRESET, assume we've lost the backend
|
||||
* connection permanently.
|
||||
*/
|
||||
switch (SOCK_ERRNO)
|
||||
@@ -785,7 +790,7 @@ pqSendSome(PGconn *conn, int len)
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not send data to server: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
/* We don't assume it's a fatal error... */
|
||||
conn->outCount = 0;
|
||||
return -1;
|
||||
@@ -803,8 +808,8 @@ pqSendSome(PGconn *conn, int len)
|
||||
/*
|
||||
* We didn't send it all, wait till we can send more.
|
||||
*
|
||||
* If the connection is in non-blocking mode we don't wait,
|
||||
* but return 1 to indicate that data is still pending.
|
||||
* If the connection is in non-blocking mode we don't wait, but
|
||||
* return 1 to indicate that data is still pending.
|
||||
*/
|
||||
if (pqIsnonblocking(conn))
|
||||
{
|
||||
@@ -876,7 +881,7 @@ pqWait(int forRead, int forWrite, PGconn *conn)
|
||||
int
|
||||
pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
|
||||
{
|
||||
int result;
|
||||
int result;
|
||||
|
||||
result = pqSocketCheck(conn, forRead, forWrite, finish_time);
|
||||
|
||||
@@ -924,14 +929,14 @@ pqWriteReady(PGconn *conn)
|
||||
static int
|
||||
pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
|
||||
{
|
||||
int result;
|
||||
int result;
|
||||
|
||||
if (!conn)
|
||||
return -1;
|
||||
if (conn->sock < 0)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("socket not open\n"));
|
||||
libpq_gettext("socket not open\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -946,18 +951,16 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
|
||||
|
||||
/* We will retry as long as we get EINTR */
|
||||
do
|
||||
{
|
||||
result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
|
||||
}
|
||||
while (result < 0 && SOCK_ERRNO == EINTR);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("select() failed: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
libpq_gettext("select() failed: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -979,13 +982,13 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
|
||||
/* We use poll(2) if available, otherwise select(2) */
|
||||
#ifdef HAVE_POLL
|
||||
struct pollfd input_fd;
|
||||
int timeout_ms;
|
||||
int timeout_ms;
|
||||
|
||||
if (!forRead && !forWrite)
|
||||
return 0;
|
||||
|
||||
input_fd.fd = sock;
|
||||
input_fd.events = POLLERR;
|
||||
input_fd.fd = sock;
|
||||
input_fd.events = POLLERR;
|
||||
input_fd.revents = 0;
|
||||
|
||||
if (forRead)
|
||||
@@ -995,12 +998,10 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
|
||||
|
||||
/* Compute appropriate timeout interval */
|
||||
if (end_time == ((time_t) -1))
|
||||
{
|
||||
timeout_ms = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (end_time > now)
|
||||
timeout_ms = (end_time - now) * 1000;
|
||||
@@ -1010,12 +1011,12 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
|
||||
|
||||
return poll(&input_fd, 1, timeout_ms);
|
||||
|
||||
#else /* !HAVE_POLL */
|
||||
#else /* !HAVE_POLL */
|
||||
|
||||
fd_set input_mask;
|
||||
fd_set output_mask;
|
||||
fd_set except_mask;
|
||||
struct timeval timeout;
|
||||
fd_set input_mask;
|
||||
fd_set output_mask;
|
||||
fd_set except_mask;
|
||||
struct timeval timeout;
|
||||
struct timeval *ptr_timeout;
|
||||
|
||||
if (!forRead && !forWrite)
|
||||
@@ -1032,12 +1033,10 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
|
||||
|
||||
/* Compute appropriate timeout interval */
|
||||
if (end_time == ((time_t) -1))
|
||||
{
|
||||
ptr_timeout = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
time_t now = time(NULL);
|
||||
|
||||
if (end_time > now)
|
||||
timeout.tv_sec = end_time - now;
|
||||
@@ -1049,7 +1048,7 @@ pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
|
||||
|
||||
return select(sock + 1, &input_mask, &output_mask,
|
||||
&except_mask, ptr_timeout);
|
||||
#endif /* HAVE_POLL */
|
||||
#endif /* HAVE_POLL */
|
||||
}
|
||||
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.4 2003/06/23 19:20:25 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.5 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ pqSetenvPoll(PGconn *conn)
|
||||
conn->next_eo->pgName, val);
|
||||
#ifdef CONNECTDEBUG
|
||||
fprintf(stderr,
|
||||
"Use environment variable %s to send %s\n",
|
||||
"Use environment variable %s to send %s\n",
|
||||
conn->next_eo->envName, setQuery);
|
||||
#endif
|
||||
if (!PQsendQuery(conn, setQuery))
|
||||
@@ -173,12 +173,12 @@ pqSetenvPoll(PGconn *conn)
|
||||
case SETENV_STATE_QUERY1_SEND:
|
||||
{
|
||||
/*
|
||||
* Issue query to get information we need. Here we must
|
||||
* use begin/commit in case autocommit is off by default
|
||||
* in a 7.3 server.
|
||||
* Issue query to get information we need. Here we
|
||||
* must use begin/commit in case autocommit is off by
|
||||
* default in a 7.3 server.
|
||||
*
|
||||
* Note: version() and getdatabaseencoding() exist in
|
||||
* all protocol-2.0-supporting backends.
|
||||
* Note: version() and getdatabaseencoding() exist in all
|
||||
* protocol-2.0-supporting backends.
|
||||
*/
|
||||
if (!PQsendQuery(conn, "begin; select version(), getdatabaseencoding(); end"))
|
||||
goto error_return;
|
||||
@@ -219,13 +219,14 @@ pqSetenvPoll(PGconn *conn)
|
||||
val = PQgetvalue(res, 0, 0);
|
||||
if (val && strncmp(val, "PostgreSQL ", 11) == 0)
|
||||
{
|
||||
char *ptr;
|
||||
char *ptr;
|
||||
|
||||
/* strip off PostgreSQL part */
|
||||
val += 11;
|
||||
|
||||
/*
|
||||
* strip off platform part (scribbles on result,
|
||||
* naughty naughty)
|
||||
* strip off platform part (scribbles on
|
||||
* result, naughty naughty)
|
||||
*/
|
||||
ptr = strchr(val, ' ');
|
||||
if (ptr)
|
||||
@@ -236,7 +237,8 @@ pqSetenvPoll(PGconn *conn)
|
||||
}
|
||||
|
||||
val = PQgetvalue(res, 0, 1);
|
||||
if (val && *val) /* null should not happen, but */
|
||||
if (val && *val) /* null should not happen,
|
||||
* but */
|
||||
pqSaveParameterStatus(conn, "server_encoding",
|
||||
val);
|
||||
|
||||
@@ -256,11 +258,11 @@ pqSetenvPoll(PGconn *conn)
|
||||
const char *query;
|
||||
|
||||
/*
|
||||
* pg_client_encoding does not exist in pre-7.2 servers.
|
||||
* So we need to be prepared for an error here. Do *not*
|
||||
* start a transaction block, except in 7.3 servers where
|
||||
* we need to prevent autocommit-off from starting a
|
||||
* transaction anyway.
|
||||
* pg_client_encoding does not exist in pre-7.2
|
||||
* servers. So we need to be prepared for an error
|
||||
* here. Do *not* start a transaction block, except
|
||||
* in 7.3 servers where we need to prevent
|
||||
* autocommit-off from starting a transaction anyway.
|
||||
*/
|
||||
if (strncmp(conn->sversion, "7.3", 3) == 0)
|
||||
query = "begin; select pg_client_encoding(); end";
|
||||
@@ -296,16 +298,17 @@ pqSetenvPoll(PGconn *conn)
|
||||
{
|
||||
/* Extract client encoding and save it */
|
||||
val = PQgetvalue(res, 0, 0);
|
||||
if (val && *val) /* null should not happen, but */
|
||||
if (val && *val) /* null should not happen,
|
||||
* but */
|
||||
pqSaveParameterStatus(conn, "client_encoding",
|
||||
val);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Error: presumably function not available, so
|
||||
* use PGCLIENTENCODING or database encoding as
|
||||
* the fallback.
|
||||
* Error: presumably function not available,
|
||||
* so use PGCLIENTENCODING or database
|
||||
* encoding as the fallback.
|
||||
*/
|
||||
val = getenv("PGCLIENTENCODING");
|
||||
if (val && *val)
|
||||
@@ -382,8 +385,8 @@ pqParseInput2(PGconn *conn)
|
||||
return;
|
||||
|
||||
/*
|
||||
* NOTIFY and NOTICE messages can happen in any state besides
|
||||
* COPY OUT; always process them right away.
|
||||
* NOTIFY and NOTICE messages can happen in any state besides COPY
|
||||
* OUT; always process them right away.
|
||||
*
|
||||
* Most other messages should only be processed while in BUSY state.
|
||||
* (In particular, in READY state we hold off further parsing
|
||||
@@ -418,13 +421,13 @@ pqParseInput2(PGconn *conn)
|
||||
*/
|
||||
if (id == 'E')
|
||||
{
|
||||
if (pqGetErrorNotice2(conn, false /* treat as notice */))
|
||||
if (pqGetErrorNotice2(conn, false /* treat as notice */ ))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pqInternalNotice(&conn->noticeHooks,
|
||||
"message type 0x%02x arrived from server while idle",
|
||||
"message type 0x%02x arrived from server while idle",
|
||||
id);
|
||||
/* Discard the unexpected message; good idea?? */
|
||||
conn->inStart = conn->inEnd;
|
||||
@@ -672,6 +675,7 @@ getAnotherTuple(PGconn *conn, bool binary)
|
||||
if (conn->curTuple == NULL)
|
||||
goto outOfMemory;
|
||||
MemSet((char *) conn->curTuple, 0, nfields * sizeof(PGresAttValue));
|
||||
|
||||
/*
|
||||
* If it's binary, fix the column format indicators. We assume
|
||||
* the backend will consistently send either B or D, not a mix.
|
||||
@@ -801,9 +805,9 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a PGresult to hold the message. We temporarily
|
||||
* lie about the result status, so that PQmakeEmptyPGresult doesn't
|
||||
* uselessly copy conn->errorMessage.
|
||||
* Make a PGresult to hold the message. We temporarily lie about the
|
||||
* result status, so that PQmakeEmptyPGresult doesn't uselessly copy
|
||||
* conn->errorMessage.
|
||||
*/
|
||||
res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
|
||||
res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
|
||||
@@ -811,13 +815,13 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
|
||||
|
||||
/*
|
||||
* Break the message into fields. We can't do very much here, but we
|
||||
* can split the severity code off, and remove trailing newlines. Also,
|
||||
* we use the heuristic that the primary message extends only to the
|
||||
* first newline --- anything after that is detail message. (In some
|
||||
* cases it'd be better classed as hint, but we can hardly be expected
|
||||
* to guess that here.)
|
||||
* can split the severity code off, and remove trailing newlines.
|
||||
* Also, we use the heuristic that the primary message extends only to
|
||||
* the first newline --- anything after that is detail message. (In
|
||||
* some cases it'd be better classed as hint, but we can hardly be
|
||||
* expected to guess that here.)
|
||||
*/
|
||||
while (workBuf.len > 0 && workBuf.data[workBuf.len-1] == '\n')
|
||||
while (workBuf.len > 0 && workBuf.data[workBuf.len - 1] == '\n')
|
||||
workBuf.data[--workBuf.len] = '\0';
|
||||
splitp = strstr(workBuf.data, ": ");
|
||||
if (splitp)
|
||||
@@ -877,10 +881,10 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
|
||||
/*
|
||||
* checkXactStatus - attempt to track transaction-block status of server
|
||||
*
|
||||
* This is called each time we receive a command-complete message. By
|
||||
* This is called each time we receive a command-complete message. By
|
||||
* watching for messages from BEGIN/COMMIT/ROLLBACK commands, we can do
|
||||
* a passable job of tracking the server's xact status. BUT: this does
|
||||
* not work at all on 7.3 servers with AUTOCOMMIT OFF. (Man, was that
|
||||
* not work at all on 7.3 servers with AUTOCOMMIT OFF. (Man, was that
|
||||
* feature ever a mistake.) Caveat user.
|
||||
*
|
||||
* The tags known here are all those used as far back as 7.0; is it worth
|
||||
@@ -895,14 +899,15 @@ checkXactStatus(PGconn *conn, const char *cmdTag)
|
||||
conn->xactStatus = PQTRANS_IDLE;
|
||||
else if (strcmp(cmdTag, "ROLLBACK") == 0)
|
||||
conn->xactStatus = PQTRANS_IDLE;
|
||||
else if (strcmp(cmdTag, "START TRANSACTION") == 0) /* 7.3 only */
|
||||
else if (strcmp(cmdTag, "START TRANSACTION") == 0) /* 7.3 only */
|
||||
conn->xactStatus = PQTRANS_INTRANS;
|
||||
|
||||
/*
|
||||
* Normally we get into INERROR state by detecting an Error message.
|
||||
* However, if we see one of these tags then we know for sure the
|
||||
* server is in abort state ...
|
||||
*/
|
||||
else if (strcmp(cmdTag, "*ABORT STATE*") == 0) /* pre-7.3 only */
|
||||
else if (strcmp(cmdTag, "*ABORT STATE*") == 0) /* pre-7.3 only */
|
||||
conn->xactStatus = PQTRANS_INERROR;
|
||||
}
|
||||
|
||||
@@ -1005,14 +1010,14 @@ pqGetCopyData2(PGconn *conn, char **buffer, int async)
|
||||
return -2;
|
||||
}
|
||||
memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
|
||||
(*buffer)[msgLength] = '\0'; /* Add terminating null */
|
||||
(*buffer)[msgLength] = '\0'; /* Add terminating null */
|
||||
|
||||
/* Mark message consumed */
|
||||
conn->inStart = conn->inCursor;
|
||||
|
||||
return msgLength;
|
||||
|
||||
nodata:
|
||||
nodata:
|
||||
/* Don't block if async read requested */
|
||||
if (async)
|
||||
return 0;
|
||||
@@ -1186,23 +1191,23 @@ pqEndcopy2(PGconn *conn)
|
||||
if (conn->errorMessage.len > 0)
|
||||
{
|
||||
/* We have to strip the trailing newline ... pain in neck... */
|
||||
char svLast = conn->errorMessage.data[conn->errorMessage.len-1];
|
||||
char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
|
||||
|
||||
if (svLast == '\n')
|
||||
conn->errorMessage.data[conn->errorMessage.len-1] = '\0';
|
||||
conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
|
||||
pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
|
||||
conn->errorMessage.data[conn->errorMessage.len-1] = svLast;
|
||||
conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
|
||||
}
|
||||
|
||||
PQclear(result);
|
||||
|
||||
/*
|
||||
* The worst case is that we've lost sync with the backend
|
||||
* entirely due to application screwup of the copy in/out protocol. To
|
||||
* recover, reset the connection (talk about using a sledgehammer...)
|
||||
* The worst case is that we've lost sync with the backend entirely
|
||||
* due to application screwup of the copy in/out protocol. To recover,
|
||||
* reset the connection (talk about using a sledgehammer...)
|
||||
*/
|
||||
pqInternalNotice(&conn->noticeHooks,
|
||||
"lost synchronization with server, resetting connection");
|
||||
"lost synchronization with server, resetting connection");
|
||||
|
||||
/*
|
||||
* Users doing non-blocking connections need to handle the reset
|
||||
@@ -1236,8 +1241,8 @@ pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
|
||||
/* PQfn already validated connection state */
|
||||
|
||||
if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
|
||||
pqPuts(" ", conn) < 0 || /* dummy string */
|
||||
if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
|
||||
pqPuts(" ", conn) < 0 || /* dummy string */
|
||||
pqPutInt(fnid, 4, conn) != 0 || /* function id */
|
||||
pqPutInt(nargs, 4, conn) != 0) /* # of args */
|
||||
{
|
||||
@@ -1397,7 +1402,7 @@ pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
*/
|
||||
char *
|
||||
pqBuildStartupPacket2(PGconn *conn, int *packetlen,
|
||||
const PQEnvironmentOption *options)
|
||||
const PQEnvironmentOption * options)
|
||||
{
|
||||
StartupPacket *startpacket;
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.4 2003/06/23 19:20:25 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.5 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -42,8 +42,8 @@ static int getParameterStatus(PGconn *conn);
|
||||
static int getNotify(PGconn *conn);
|
||||
static int getCopyStart(PGconn *conn, ExecStatusType copytype);
|
||||
static int getReadyForQuery(PGconn *conn);
|
||||
static int build_startup_packet(const PGconn *conn, char *packet,
|
||||
const PQEnvironmentOption *options);
|
||||
static int build_startup_packet(const PGconn *conn, char *packet,
|
||||
const PQEnvironmentOption * options);
|
||||
|
||||
|
||||
/*
|
||||
@@ -98,20 +98,20 @@ pqParseInput3(PGconn *conn)
|
||||
if (avail < msgLength)
|
||||
{
|
||||
/*
|
||||
* Before returning, enlarge the input buffer if needed to hold
|
||||
* the whole message. This is better than leaving it to
|
||||
* pqReadData because we can avoid multiple cycles of realloc()
|
||||
* when the message is large; also, we can implement a reasonable
|
||||
* recovery strategy if we are unable to make the buffer big
|
||||
* enough.
|
||||
* Before returning, enlarge the input buffer if needed to
|
||||
* hold the whole message. This is better than leaving it to
|
||||
* pqReadData because we can avoid multiple cycles of
|
||||
* realloc() when the message is large; also, we can implement
|
||||
* a reasonable recovery strategy if we are unable to make the
|
||||
* buffer big enough.
|
||||
*/
|
||||
if (pqCheckInBufferSpace(conn->inCursor + msgLength, conn))
|
||||
{
|
||||
/*
|
||||
* XXX add some better recovery code... plan is to skip
|
||||
* over the message using its length, then report an error.
|
||||
* For the moment, just treat this like loss of sync (which
|
||||
* indeed it might be!)
|
||||
* over the message using its length, then report an
|
||||
* error. For the moment, just treat this like loss of
|
||||
* sync (which indeed it might be!)
|
||||
*/
|
||||
handleSyncLoss(conn, id, msgLength);
|
||||
}
|
||||
@@ -119,8 +119,8 @@ pqParseInput3(PGconn *conn)
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTIFY and NOTICE messages can happen in any state; always process
|
||||
* them right away.
|
||||
* NOTIFY and NOTICE messages can happen in any state; always
|
||||
* process them right away.
|
||||
*
|
||||
* Most other messages should only be processed while in BUSY state.
|
||||
* (In particular, in READY state we hold off further parsing
|
||||
@@ -153,15 +153,15 @@ pqParseInput3(PGconn *conn)
|
||||
/*
|
||||
* Unexpected message in IDLE state; need to recover somehow.
|
||||
* ERROR messages are displayed using the notice processor;
|
||||
* ParameterStatus is handled normally;
|
||||
* anything else is just dropped on the floor after displaying
|
||||
* a suitable warning notice. (An ERROR is very possibly the
|
||||
* backend telling us why it is about to close the connection,
|
||||
* so we don't want to just discard it...)
|
||||
* ParameterStatus is handled normally; anything else is just
|
||||
* dropped on the floor after displaying a suitable warning
|
||||
* notice. (An ERROR is very possibly the backend telling us
|
||||
* why it is about to close the connection, so we don't want
|
||||
* to just discard it...)
|
||||
*/
|
||||
if (id == 'E')
|
||||
{
|
||||
if (pqGetErrorNotice3(conn, false /* treat as notice */))
|
||||
if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
|
||||
return;
|
||||
}
|
||||
else if (id == 'S')
|
||||
@@ -172,7 +172,7 @@ pqParseInput3(PGconn *conn)
|
||||
else
|
||||
{
|
||||
pqInternalNotice(&conn->noticeHooks,
|
||||
"message type 0x%02x arrived from server while idle",
|
||||
"message type 0x%02x arrived from server while idle",
|
||||
id);
|
||||
/* Discard the unexpected message */
|
||||
conn->inCursor += msgLength;
|
||||
@@ -262,11 +262,12 @@ pqParseInput3(PGconn *conn)
|
||||
return;
|
||||
}
|
||||
else if (conn->result != NULL &&
|
||||
conn->result->resultStatus == PGRES_FATAL_ERROR)
|
||||
conn->result->resultStatus == PGRES_FATAL_ERROR)
|
||||
{
|
||||
/*
|
||||
* We've already choked for some reason. Just discard
|
||||
* tuples till we get to the end of the query.
|
||||
* We've already choked for some reason. Just
|
||||
* discard tuples till we get to the end of the
|
||||
* query.
|
||||
*/
|
||||
conn->inCursor += msgLength;
|
||||
}
|
||||
@@ -274,7 +275,7 @@ pqParseInput3(PGconn *conn)
|
||||
{
|
||||
/* Set up to report error at end of query */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
|
||||
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
|
||||
pqSaveErrorResult(conn);
|
||||
/* Discard the unexpected message */
|
||||
conn->inCursor += msgLength;
|
||||
@@ -292,16 +293,18 @@ pqParseInput3(PGconn *conn)
|
||||
conn->copy_already_done = 0;
|
||||
break;
|
||||
case 'd': /* Copy Data */
|
||||
|
||||
/*
|
||||
* If we see Copy Data, just silently drop it. This
|
||||
* If we see Copy Data, just silently drop it. This
|
||||
* would only occur if application exits COPY OUT mode
|
||||
* too early.
|
||||
*/
|
||||
conn->inCursor += msgLength;
|
||||
break;
|
||||
case 'c': /* Copy Done */
|
||||
|
||||
/*
|
||||
* If we see Copy Done, just silently drop it. This
|
||||
* If we see Copy Done, just silently drop it. This
|
||||
* is the normal case during PQendcopy. We will keep
|
||||
* swallowing data, expecting to see command-complete
|
||||
* for the COPY command.
|
||||
@@ -352,11 +355,11 @@ handleSyncLoss(PGconn *conn, char id, int msgLength)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
"lost synchronization with server: got message type \"%c\", length %d\n"),
|
||||
"lost synchronization with server: got message type \"%c\", length %d\n"),
|
||||
id, msgLength);
|
||||
/* build an error result holding the error message */
|
||||
pqSaveErrorResult(conn);
|
||||
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
|
||||
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
|
||||
|
||||
pqsecure_close(conn);
|
||||
closesocket(conn->sock);
|
||||
@@ -488,7 +491,7 @@ getAnotherTuple(PGconn *conn, int msgLength)
|
||||
{
|
||||
/* Replace partially constructed result with an error result */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("unexpected field count in D message\n"));
|
||||
libpq_gettext("unexpected field count in D message\n"));
|
||||
pqSaveErrorResult(conn);
|
||||
/* Discard the failed message by pretending we read it */
|
||||
conn->inCursor = conn->inStart + 5 + msgLength;
|
||||
@@ -512,7 +515,7 @@ getAnotherTuple(PGconn *conn, int msgLength)
|
||||
vlen = 0;
|
||||
if (tup[i].value == NULL)
|
||||
{
|
||||
bool isbinary = (result->attDescs[i].format != 0);
|
||||
bool isbinary = (result->attDescs[i].format != 0);
|
||||
|
||||
tup[i].value = (char *) pqResultAlloc(result, vlen + 1, isbinary);
|
||||
if (tup[i].value == NULL)
|
||||
@@ -536,9 +539,10 @@ getAnotherTuple(PGconn *conn, int msgLength)
|
||||
return 0;
|
||||
|
||||
outOfMemory:
|
||||
|
||||
/*
|
||||
* Replace partially constructed result with an error result.
|
||||
* First discard the old result to try to win back some memory.
|
||||
* Replace partially constructed result with an error result. First
|
||||
* discard the old result to try to win back some memory.
|
||||
*/
|
||||
pqClearAsyncResult(conn);
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
@@ -567,17 +571,18 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
|
||||
const char *val;
|
||||
|
||||
/*
|
||||
* Make a PGresult to hold the accumulated fields. We temporarily
|
||||
* lie about the result status, so that PQmakeEmptyPGresult doesn't
|
||||
* Make a PGresult to hold the accumulated fields. We temporarily lie
|
||||
* about the result status, so that PQmakeEmptyPGresult doesn't
|
||||
* uselessly copy conn->errorMessage.
|
||||
*/
|
||||
res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
|
||||
res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
|
||||
|
||||
/*
|
||||
* Since the fields might be pretty long, we create a temporary
|
||||
* PQExpBuffer rather than using conn->workBuffer. workBuffer is
|
||||
* intended for stuff that is expected to be short. We shouldn't
|
||||
* use conn->errorMessage either, since this might be only a notice.
|
||||
* intended for stuff that is expected to be short. We shouldn't use
|
||||
* conn->errorMessage either, since this might be only a notice.
|
||||
*/
|
||||
initPQExpBuffer(&workBuf);
|
||||
|
||||
@@ -599,19 +604,19 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
|
||||
* Now build the "overall" error message for PQresultErrorMessage.
|
||||
*/
|
||||
resetPQExpBuffer(&workBuf);
|
||||
val = PQresultErrorField(res, 'S'); /* Severity */
|
||||
val = PQresultErrorField(res, 'S'); /* Severity */
|
||||
if (val)
|
||||
appendPQExpBuffer(&workBuf, "%s: ", val);
|
||||
if (conn->verbosity == PQERRORS_VERBOSE)
|
||||
{
|
||||
val = PQresultErrorField(res, 'C'); /* SQLSTATE Code */
|
||||
val = PQresultErrorField(res, 'C'); /* SQLSTATE Code */
|
||||
if (val)
|
||||
appendPQExpBuffer(&workBuf, "%s: ", val);
|
||||
}
|
||||
val = PQresultErrorField(res, 'M'); /* Primary message */
|
||||
val = PQresultErrorField(res, 'M'); /* Primary message */
|
||||
if (val)
|
||||
appendPQExpBufferStr(&workBuf, val);
|
||||
val = PQresultErrorField(res, 'P'); /* Position */
|
||||
val = PQresultErrorField(res, 'P'); /* Position */
|
||||
if (val)
|
||||
{
|
||||
/* translator: %s represents a digit string */
|
||||
@@ -620,13 +625,13 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
|
||||
appendPQExpBufferChar(&workBuf, '\n');
|
||||
if (conn->verbosity != PQERRORS_TERSE)
|
||||
{
|
||||
val = PQresultErrorField(res, 'D'); /* Detail */
|
||||
val = PQresultErrorField(res, 'D'); /* Detail */
|
||||
if (val)
|
||||
appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL: %s\n"), val);
|
||||
val = PQresultErrorField(res, 'H'); /* Hint */
|
||||
val = PQresultErrorField(res, 'H'); /* Hint */
|
||||
if (val)
|
||||
appendPQExpBuffer(&workBuf, libpq_gettext("HINT: %s\n"), val);
|
||||
val = PQresultErrorField(res, 'W'); /* Where */
|
||||
val = PQresultErrorField(res, 'W'); /* Where */
|
||||
if (val)
|
||||
appendPQExpBuffer(&workBuf, libpq_gettext("CONTEXT: %s\n"), val);
|
||||
}
|
||||
@@ -637,7 +642,7 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
|
||||
|
||||
valf = PQresultErrorField(res, 'F'); /* File */
|
||||
vall = PQresultErrorField(res, 'L'); /* Line */
|
||||
val = PQresultErrorField(res, 'R'); /* Routine */
|
||||
val = PQresultErrorField(res, 'R'); /* Routine */
|
||||
if (val || valf || vall)
|
||||
{
|
||||
appendPQExpBufferStr(&workBuf, libpq_gettext("LOCATION: "));
|
||||
@@ -740,9 +745,9 @@ getNotify(PGconn *conn)
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the strings right after the PQnotify structure so it
|
||||
* can all be freed at once. We don't use NAMEDATALEN because we
|
||||
* don't want to tie this interface to a specific server name length.
|
||||
* Store the strings right after the PQnotify structure so it can all
|
||||
* be freed at once. We don't use NAMEDATALEN because we don't want
|
||||
* to tie this interface to a specific server name length.
|
||||
*/
|
||||
nmlen = strlen(svname);
|
||||
extralen = strlen(conn->workBuffer.data);
|
||||
@@ -869,9 +874,9 @@ pqGetCopyData3(PGconn *conn, char **buffer, int async)
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* Do we have the next input message? To make life simpler for async
|
||||
* callers, we keep returning 0 until the next message is fully
|
||||
* available, even if it is not Copy Data.
|
||||
* Do we have the next input message? To make life simpler for
|
||||
* async callers, we keep returning 0 until the next message is
|
||||
* fully available, even if it is not Copy Data.
|
||||
*/
|
||||
conn->inCursor = conn->inStart;
|
||||
if (pqGetc(&id, conn))
|
||||
@@ -908,7 +913,7 @@ pqGetCopyData3(PGconn *conn, char **buffer, int async)
|
||||
return -2;
|
||||
}
|
||||
memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
|
||||
(*buffer)[msgLength] = '\0'; /* Add terminating null */
|
||||
(*buffer)[msgLength] = '\0'; /* Add terminating null */
|
||||
|
||||
/* Mark message consumed */
|
||||
conn->inStart = conn->inCursor + msgLength;
|
||||
@@ -920,7 +925,7 @@ pqGetCopyData3(PGconn *conn, char **buffer, int async)
|
||||
conn->inStart = conn->inCursor;
|
||||
continue;
|
||||
|
||||
nodata:
|
||||
nodata:
|
||||
/* Don't block if async read requested */
|
||||
if (async)
|
||||
return 0;
|
||||
@@ -946,12 +951,12 @@ pqGetline3(PGconn *conn, char *s, int maxlen)
|
||||
conn->copy_is_binary)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("PQgetline: not doing text COPY OUT\n"));
|
||||
libpq_gettext("PQgetline: not doing text COPY OUT\n"));
|
||||
*s = '\0';
|
||||
return EOF;
|
||||
}
|
||||
|
||||
while ((status = PQgetlineAsync(conn, s, maxlen-1)) == 0)
|
||||
while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
|
||||
{
|
||||
/* need to load more data */
|
||||
if (pqWait(TRUE, FALSE, conn) ||
|
||||
@@ -970,9 +975,9 @@ pqGetline3(PGconn *conn, char *s, int maxlen)
|
||||
}
|
||||
|
||||
/* Add null terminator, and strip trailing \n if present */
|
||||
if (s[status-1] == '\n')
|
||||
if (s[status - 1] == '\n')
|
||||
{
|
||||
s[status-1] = '\0';
|
||||
s[status - 1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -999,8 +1004,9 @@ pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
|
||||
|
||||
/*
|
||||
* Recognize the next input message. To make life simpler for async
|
||||
* callers, we keep returning 0 until the next message is fully available
|
||||
* even if it is not Copy Data. This should keep PQendcopy from blocking.
|
||||
* callers, we keep returning 0 until the next message is fully
|
||||
* available even if it is not Copy Data. This should keep PQendcopy
|
||||
* from blocking.
|
||||
*/
|
||||
conn->inCursor = conn->inStart;
|
||||
if (pqGetc(&id, conn))
|
||||
@@ -1012,15 +1018,15 @@ pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Cannot proceed unless it's a Copy Data message. Anything else means
|
||||
* end of copy mode.
|
||||
* Cannot proceed unless it's a Copy Data message. Anything else
|
||||
* means end of copy mode.
|
||||
*/
|
||||
if (id != 'd')
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Move data from libpq's buffer to the caller's. In the case where
|
||||
* a prior call found the caller's buffer too small, we use
|
||||
* Move data from libpq's buffer to the caller's. In the case where a
|
||||
* prior call found the caller's buffer too small, we use
|
||||
* conn->copy_already_done to remember how much of the row was already
|
||||
* returned to the caller.
|
||||
*/
|
||||
@@ -1084,12 +1090,12 @@ pqEndcopy3(PGconn *conn)
|
||||
resetPQExpBuffer(&conn->errorMessage);
|
||||
|
||||
/*
|
||||
* Non blocking connections may have to abort at this point. If everyone
|
||||
* played the game there should be no problem, but in error scenarios
|
||||
* the expected messages may not have arrived yet. (We are assuming that
|
||||
* the backend's packetizing will ensure that CommandComplete arrives
|
||||
* along with the CopyDone; are there corner cases where that doesn't
|
||||
* happen?)
|
||||
* Non blocking connections may have to abort at this point. If
|
||||
* everyone played the game there should be no problem, but in error
|
||||
* scenarios the expected messages may not have arrived yet. (We are
|
||||
* assuming that the backend's packetizing will ensure that
|
||||
* CommandComplete arrives along with the CopyDone; are there corner
|
||||
* cases where that doesn't happen?)
|
||||
*/
|
||||
if (pqIsnonblocking(conn) && PQisBusy(conn))
|
||||
return (1);
|
||||
@@ -1114,12 +1120,12 @@ pqEndcopy3(PGconn *conn)
|
||||
if (conn->errorMessage.len > 0)
|
||||
{
|
||||
/* We have to strip the trailing newline ... pain in neck... */
|
||||
char svLast = conn->errorMessage.data[conn->errorMessage.len-1];
|
||||
char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
|
||||
|
||||
if (svLast == '\n')
|
||||
conn->errorMessage.data[conn->errorMessage.len-1] = '\0';
|
||||
conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
|
||||
pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
|
||||
conn->errorMessage.data[conn->errorMessage.len-1] = svLast;
|
||||
conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
|
||||
}
|
||||
|
||||
PQclear(result);
|
||||
@@ -1148,11 +1154,11 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
|
||||
/* PQfn already validated connection state */
|
||||
|
||||
if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
|
||||
pqPutInt(fnid, 4, conn) < 0 || /* function id */
|
||||
pqPutInt(1, 2, conn) < 0 || /* # of format codes */
|
||||
pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
|
||||
pqPutInt(nargs, 2, conn) < 0) /* # of args */
|
||||
if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
|
||||
pqPutInt(fnid, 4, conn) < 0 || /* function id */
|
||||
pqPutInt(1, 2, conn) < 0 || /* # of format codes */
|
||||
pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
|
||||
pqPutInt(nargs, 2, conn) < 0) /* # of args */
|
||||
{
|
||||
pqHandleSendFailure(conn);
|
||||
return NULL;
|
||||
@@ -1253,9 +1259,9 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
{
|
||||
/*
|
||||
* XXX add some better recovery code... plan is to skip
|
||||
* over the message using its length, then report an error.
|
||||
* For the moment, just treat this like loss of sync (which
|
||||
* indeed it might be!)
|
||||
* over the message using its length, then report an
|
||||
* error. For the moment, just treat this like loss of
|
||||
* sync (which indeed it might be!)
|
||||
*/
|
||||
handleSyncLoss(conn, id, msgLength);
|
||||
break;
|
||||
@@ -1352,9 +1358,9 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
*/
|
||||
char *
|
||||
pqBuildStartupPacket3(PGconn *conn, int *packetlen,
|
||||
const PQEnvironmentOption *options)
|
||||
const PQEnvironmentOption * options)
|
||||
{
|
||||
char *startpacket;
|
||||
char *startpacket;
|
||||
|
||||
*packetlen = build_startup_packet(conn, NULL, options);
|
||||
startpacket = (char *) malloc(*packetlen);
|
||||
@@ -1375,9 +1381,9 @@ pqBuildStartupPacket3(PGconn *conn, int *packetlen,
|
||||
*/
|
||||
static int
|
||||
build_startup_packet(const PGconn *conn, char *packet,
|
||||
const PQEnvironmentOption *options)
|
||||
const PQEnvironmentOption * options)
|
||||
{
|
||||
int packet_len = 0;
|
||||
int packet_len = 0;
|
||||
const PQEnvironmentOption *next_eo;
|
||||
|
||||
/* Protocol version comes first. */
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.26 2003/08/04 00:26:49 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-secure.c,v 1.27 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The client *requires* a valid server certificate. Since
|
||||
@@ -123,6 +123,7 @@
|
||||
|
||||
#ifdef USE_SSL
|
||||
static int verify_cb(int ok, X509_STORE_CTX *ctx);
|
||||
|
||||
#ifdef NOT_USED
|
||||
static int verify_peer(PGconn *);
|
||||
#endif
|
||||
@@ -195,7 +196,6 @@ OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
|
||||
AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
|
||||
KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
|
||||
-----END DH PARAMETERS-----\n";
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@@ -280,7 +280,7 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl)
|
||||
{
|
||||
rloop:
|
||||
rloop:
|
||||
n = SSL_read(conn->ssl, ptr, len);
|
||||
switch (SSL_get_error(conn->ssl, n))
|
||||
{
|
||||
@@ -290,27 +290,29 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
|
||||
n = 0;
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
|
||||
/*
|
||||
* Returning 0 here would cause caller to wait for read-ready,
|
||||
* which is not correct since what SSL wants is wait for
|
||||
* write-ready. The former could get us stuck in an infinite
|
||||
* wait, so don't risk it; busy-loop instead.
|
||||
* Returning 0 here would cause caller to wait for
|
||||
* read-ready, which is not correct since what SSL wants
|
||||
* is wait for write-ready. The former could get us stuck
|
||||
* in an infinite wait, so don't risk it; busy-loop
|
||||
* instead.
|
||||
*/
|
||||
goto rloop;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
{
|
||||
char sebuf[256];
|
||||
|
||||
if (n == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
{
|
||||
char sebuf[256];
|
||||
|
||||
break;
|
||||
}
|
||||
if (n == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
|
||||
break;
|
||||
}
|
||||
case SSL_ERROR_SSL:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
|
||||
@@ -322,7 +324,7 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
|
||||
break;
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -354,6 +356,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
|
||||
case SSL_ERROR_NONE:
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
|
||||
/*
|
||||
* Returning 0 here causes caller to wait for write-ready,
|
||||
* which is not really the right thing, but it's the best
|
||||
@@ -365,18 +368,18 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
|
||||
n = 0;
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
{
|
||||
char sebuf[256];
|
||||
{
|
||||
char sebuf[256];
|
||||
|
||||
if (n == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
if (n == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
break;
|
||||
}
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
break;
|
||||
}
|
||||
case SSL_ERROR_SSL:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
|
||||
@@ -388,7 +391,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
|
||||
break;
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -442,10 +445,11 @@ verify_peer(PGconn *conn)
|
||||
len = sizeof(addr);
|
||||
if (getpeername(conn->sock, &addr, &len) == -1)
|
||||
{
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("error querying socket: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -455,13 +459,13 @@ verify_peer(PGconn *conn)
|
||||
|
||||
{
|
||||
struct hostent hpstr;
|
||||
char buf[BUFSIZ];
|
||||
int herrno = 0;
|
||||
char buf[BUFSIZ];
|
||||
int herrno = 0;
|
||||
|
||||
pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
|
||||
&h, &herrno);
|
||||
&h, &herrno);
|
||||
}
|
||||
|
||||
|
||||
/* what do we know about the peer's common name? */
|
||||
if (h == NULL)
|
||||
{
|
||||
@@ -485,7 +489,7 @@ verify_peer(PGconn *conn)
|
||||
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("unsupported protocol\n"));
|
||||
libpq_gettext("unsupported protocol\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -514,7 +518,7 @@ verify_peer(PGconn *conn)
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
"server common name \"%s\" does not resolve to peer address\n"),
|
||||
"server common name \"%s\" does not resolve to peer address\n"),
|
||||
conn->peer_cn);
|
||||
}
|
||||
|
||||
@@ -532,7 +536,7 @@ verify_peer(PGconn *conn)
|
||||
static DH *
|
||||
load_dh_file(int keylength)
|
||||
{
|
||||
char pwdbuf[BUFSIZ];
|
||||
char pwdbuf[BUFSIZ];
|
||||
struct passwd pwdstr;
|
||||
struct passwd *pwd = NULL;
|
||||
FILE *fp;
|
||||
@@ -540,8 +544,8 @@ load_dh_file(int keylength)
|
||||
DH *dh = NULL;
|
||||
int codes;
|
||||
|
||||
if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
|
||||
return NULL;
|
||||
if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)
|
||||
return NULL;
|
||||
|
||||
/* attempt to open file. It's not an error if it doesn't exist. */
|
||||
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
|
||||
@@ -674,7 +678,7 @@ tmp_dh_cb(SSL *s, int is_export, int keylength)
|
||||
static int
|
||||
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
{
|
||||
char pwdbuf[BUFSIZ];
|
||||
char pwdbuf[BUFSIZ];
|
||||
struct passwd pwdstr;
|
||||
struct passwd *pwd = NULL;
|
||||
struct stat buf,
|
||||
@@ -683,10 +687,10 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
FILE *fp;
|
||||
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
|
||||
int (*cb) () = NULL; /* how to read user password */
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
|
||||
if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
|
||||
if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not get user information\n"));
|
||||
@@ -730,7 +734,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
buf.st_uid != getuid())
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("private key (%s) has wrong permissions\n"), fnbuf);
|
||||
libpq_gettext("private key (%s) has wrong permissions\n"), fnbuf);
|
||||
X509_free(*x509);
|
||||
return -1;
|
||||
}
|
||||
@@ -746,7 +750,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("private key (%s) changed during execution\n"), fnbuf);
|
||||
libpq_gettext("private key (%s) changed during execution\n"), fnbuf);
|
||||
X509_free(*x509);
|
||||
return -1;
|
||||
}
|
||||
@@ -782,7 +786,7 @@ static int
|
||||
initialize_SSL(PGconn *conn)
|
||||
{
|
||||
struct stat buf;
|
||||
char pwdbuf[BUFSIZ];
|
||||
char pwdbuf[BUFSIZ];
|
||||
struct passwd pwdstr;
|
||||
struct passwd *pwd = NULL;
|
||||
char fnbuf[2048];
|
||||
@@ -801,7 +805,7 @@ initialize_SSL(PGconn *conn)
|
||||
}
|
||||
}
|
||||
|
||||
if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
|
||||
if (pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0)
|
||||
{
|
||||
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
|
||||
pwd->pw_dir);
|
||||
@@ -809,18 +813,19 @@ initialize_SSL(PGconn *conn)
|
||||
{
|
||||
return 0;
|
||||
#ifdef NOT_USED
|
||||
char sebuf[256];
|
||||
char sebuf[256];
|
||||
|
||||
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not read root certificate list (%s): %s\n"),
|
||||
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
libpq_gettext("could not read root certificate list (%s): %s\n"),
|
||||
fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
if (!SSL_CTX_load_verify_locations(SSL_context, fnbuf, 0))
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("could not read root certificate list (%s): %s\n"),
|
||||
libpq_gettext("could not read root certificate list (%s): %s\n"),
|
||||
fnbuf, SSLerrmessage());
|
||||
return -1;
|
||||
}
|
||||
@@ -868,24 +873,24 @@ open_client_SSL(PGconn *conn)
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
return PGRES_POLLING_READING;
|
||||
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return PGRES_POLLING_WRITING;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
{
|
||||
char sebuf[256];
|
||||
|
||||
if (r == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
{
|
||||
char sebuf[256];
|
||||
|
||||
if (r == -1)
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: %s\n"),
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
close_SSL(conn);
|
||||
return PGRES_POLLING_FAILED;
|
||||
}
|
||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||
else
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
|
||||
close_SSL(conn);
|
||||
return PGRES_POLLING_FAILED;
|
||||
}
|
||||
case SSL_ERROR_SSL:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
|
||||
@@ -894,7 +899,7 @@ open_client_SSL(PGconn *conn)
|
||||
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
libpq_gettext("Unknown SSL error code\n"));
|
||||
close_SSL(conn);
|
||||
return PGRES_POLLING_FAILED;
|
||||
}
|
||||
@@ -904,6 +909,7 @@ open_client_SSL(PGconn *conn)
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
|
||||
|
||||
/*
|
||||
* this eliminates simple man-in-the-middle attacks and simple
|
||||
* impersonations
|
||||
@@ -942,6 +948,7 @@ open_client_SSL(PGconn *conn)
|
||||
|
||||
#ifdef NOT_USED
|
||||
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
|
||||
|
||||
/*
|
||||
* this is necessary to eliminate man-in-the-middle attacks and
|
||||
* impersonations where the attacker somehow learned the server's
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: libpq-fe.h,v 1.94 2003/06/21 21:51:34 tgl Exp $
|
||||
* $Id: libpq-fe.h,v 1.95 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,8 +39,8 @@ typedef enum
|
||||
{
|
||||
/*
|
||||
* Although it is okay to add to this list, values which become unused
|
||||
* should never be removed, nor should constants be redefined - that would
|
||||
* break compatibility with existing code.
|
||||
* should never be removed, nor should constants be redefined - that
|
||||
* would break compatibility with existing code.
|
||||
*/
|
||||
CONNECTION_OK,
|
||||
CONNECTION_BAD,
|
||||
@@ -67,8 +67,8 @@ typedef enum
|
||||
PGRES_POLLING_READING, /* These two indicate that one may */
|
||||
PGRES_POLLING_WRITING, /* use select before polling again. */
|
||||
PGRES_POLLING_OK,
|
||||
PGRES_POLLING_ACTIVE /* unused; keep for awhile for
|
||||
* backwards compatibility */
|
||||
PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards
|
||||
* compatibility */
|
||||
} PostgresPollingStatusType;
|
||||
|
||||
typedef enum
|
||||
@@ -95,14 +95,14 @@ typedef enum
|
||||
PQTRANS_INTRANS, /* idle, within transaction block */
|
||||
PQTRANS_INERROR, /* idle, within failed transaction */
|
||||
PQTRANS_UNKNOWN /* cannot determine status */
|
||||
} PGTransactionStatusType;
|
||||
} PGTransactionStatusType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PQERRORS_TERSE, /* single-line error messages */
|
||||
PQERRORS_DEFAULT, /* recommended style */
|
||||
PQERRORS_VERBOSE /* all the facts, ma'am */
|
||||
} PGVerbosity;
|
||||
} PGVerbosity;
|
||||
|
||||
/* PGconn encapsulates a connection to the backend.
|
||||
* The contents of this struct are not supposed to be known to applications.
|
||||
@@ -246,7 +246,7 @@ extern char *PQoptions(const PGconn *conn);
|
||||
extern ConnStatusType PQstatus(const PGconn *conn);
|
||||
extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
|
||||
extern const char *PQparameterStatus(const PGconn *conn,
|
||||
const char *paramName);
|
||||
const char *paramName);
|
||||
extern int PQprotocolVersion(const PGconn *conn);
|
||||
extern char *PQerrorMessage(const PGconn *conn);
|
||||
extern int PQsocket(const PGconn *conn);
|
||||
@@ -268,8 +268,8 @@ extern void PQuntrace(PGconn *conn);
|
||||
|
||||
/* Override default notice handling routines */
|
||||
extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn,
|
||||
PQnoticeReceiver proc,
|
||||
void *arg);
|
||||
PQnoticeReceiver proc,
|
||||
void *arg);
|
||||
extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
|
||||
PQnoticeProcessor proc,
|
||||
void *arg);
|
||||
@@ -279,24 +279,24 @@ extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
|
||||
/* Simple synchronous query */
|
||||
extern PGresult *PQexec(PGconn *conn, const char *query);
|
||||
extern PGresult *PQexecParams(PGconn *conn,
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char * const *paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat);
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char *const * paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat);
|
||||
|
||||
/* Interface for multiple-result or asynchronous queries */
|
||||
extern int PQsendQuery(PGconn *conn, const char *query);
|
||||
extern int PQsendQueryParams(PGconn *conn,
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char * const *paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat);
|
||||
extern int PQsendQueryParams(PGconn *conn,
|
||||
const char *command,
|
||||
int nParams,
|
||||
const Oid *paramTypes,
|
||||
const char *const * paramValues,
|
||||
const int *paramLengths,
|
||||
const int *paramFormats,
|
||||
int resultFormat);
|
||||
extern PGresult *PQgetResult(PGconn *conn);
|
||||
|
||||
/* Routines for managing an asynchronous query */
|
||||
@@ -310,6 +310,7 @@ extern PGnotify *PQnotifies(PGconn *conn);
|
||||
extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
|
||||
extern int PQputCopyEnd(PGconn *conn, const char *errormsg);
|
||||
extern int PQgetCopyData(PGconn *conn, char **buffer, int async);
|
||||
|
||||
/* Deprecated routines for copy in/out */
|
||||
extern int PQgetline(PGconn *conn, char *string, int length);
|
||||
extern int PQputline(PGconn *conn, const char *string);
|
||||
@@ -388,21 +389,24 @@ extern unsigned char *PQunescapeBytea(const unsigned char *strtext,
|
||||
|
||||
/* === in fe-print.c === */
|
||||
|
||||
extern void PQprint(FILE *fout, /* output stream */
|
||||
const PGresult *res,
|
||||
const PQprintOpt *ps); /* option structure */
|
||||
extern void
|
||||
PQprint(FILE *fout, /* output stream */
|
||||
const PGresult *res,
|
||||
const PQprintOpt *ps); /* option structure */
|
||||
|
||||
/*
|
||||
* really old printing routines
|
||||
*/
|
||||
extern void PQdisplayTuples(const PGresult *res,
|
||||
extern void
|
||||
PQdisplayTuples(const PGresult *res,
|
||||
FILE *fp, /* where to send the output */
|
||||
int fillAlign, /* pad the fields with spaces */
|
||||
const char *fieldSep, /* field separator */
|
||||
int printHeader, /* display headers? */
|
||||
int quiet);
|
||||
|
||||
extern void PQprintTuples(const PGresult *res,
|
||||
extern void
|
||||
PQprintTuples(const PGresult *res,
|
||||
FILE *fout, /* output stream */
|
||||
int printAttName, /* print attribute names */
|
||||
int terseOutput, /* delimiter bars */
|
||||
|
@@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: libpq-int.h,v 1.78 2003/08/01 21:27:27 tgl Exp $
|
||||
* $Id: libpq-int.h,v 1.79 2003/08/04 00:43:33 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -120,16 +120,16 @@ typedef struct pgMessageField
|
||||
struct pgMessageField *next; /* list link */
|
||||
char code; /* field code */
|
||||
char contents[1]; /* field value (VARIABLE LENGTH) */
|
||||
} PGMessageField;
|
||||
} PGMessageField;
|
||||
|
||||
/* Fields needed for notice handling */
|
||||
typedef struct
|
||||
{
|
||||
PQnoticeReceiver noticeRec; /* notice message receiver */
|
||||
PQnoticeReceiver noticeRec; /* notice message receiver */
|
||||
void *noticeRecArg;
|
||||
PQnoticeProcessor noticeProc; /* notice message processor */
|
||||
PQnoticeProcessor noticeProc; /* notice message processor */
|
||||
void *noticeProcArg;
|
||||
} PGNoticeHooks;
|
||||
} PGNoticeHooks;
|
||||
|
||||
struct pg_result
|
||||
{
|
||||
@@ -201,16 +201,16 @@ typedef struct PQEnvironmentOption
|
||||
{
|
||||
const char *envName, /* name of an environment variable */
|
||||
*pgName; /* name of corresponding SET variable */
|
||||
} PQEnvironmentOption;
|
||||
} PQEnvironmentOption;
|
||||
|
||||
/* Typedef for parameter-status list entries */
|
||||
typedef struct pgParameterStatus
|
||||
{
|
||||
struct pgParameterStatus *next; /* list link */
|
||||
struct pgParameterStatus *next; /* list link */
|
||||
char *name; /* parameter name */
|
||||
char *value; /* parameter value */
|
||||
/* Note: name and value are stored in same malloc block as struct is */
|
||||
} pgParameterStatus;
|
||||
} pgParameterStatus;
|
||||
|
||||
/* large-object-access data ... allocated only if large-object code is used. */
|
||||
typedef struct pgLobjfuncs
|
||||
@@ -244,7 +244,7 @@ struct pg_conn
|
||||
* default constructed from pgport */
|
||||
char *pgtty; /* tty on which the backend messages is
|
||||
* displayed (OBSOLETE, NOT USED) */
|
||||
char *connect_timeout; /* connection timeout (numeric string) */
|
||||
char *connect_timeout; /* connection timeout (numeric string) */
|
||||
char *pgoptions; /* options to start the backend with */
|
||||
char *dbName; /* database name */
|
||||
char *pguser; /* Postgres username and password, if any */
|
||||
@@ -264,8 +264,9 @@ struct pg_conn
|
||||
/* note: xactStatus never changes to ACTIVE */
|
||||
int nonblocking; /* whether this connection is using a
|
||||
* blocking socket to the backend or not */
|
||||
char copy_is_binary; /* 1 = copy binary, 0 = copy text */
|
||||
int copy_already_done; /* # bytes already returned in COPY OUT */
|
||||
char copy_is_binary; /* 1 = copy binary, 0 = copy text */
|
||||
int copy_already_done; /* # bytes already returned in
|
||||
* COPY OUT */
|
||||
Dllist *notifyList; /* Notify msgs not yet handed to
|
||||
* application */
|
||||
|
||||
@@ -279,8 +280,8 @@ struct pg_conn
|
||||
/* Transient state needed while establishing connection */
|
||||
struct addrinfo *addrlist; /* list of possible backend addresses */
|
||||
struct addrinfo *addr_cur; /* the one currently being tried */
|
||||
int addrlist_family; /* needed to know how to free addrlist */
|
||||
PGSetenvStatusType setenv_state; /* for 2.0 protocol only */
|
||||
int addrlist_family; /* needed to know how to free addrlist */
|
||||
PGSetenvStatusType setenv_state; /* for 2.0 protocol only */
|
||||
const PQEnvironmentOption *next_eo;
|
||||
|
||||
/* Miscellaneous stuff */
|
||||
@@ -288,9 +289,9 @@ struct pg_conn
|
||||
int be_key; /* key of backend --- needed for cancels */
|
||||
char md5Salt[4]; /* password salt received from backend */
|
||||
char cryptSalt[2]; /* password salt received from backend */
|
||||
pgParameterStatus *pstatus; /* ParameterStatus data */
|
||||
int client_encoding; /* encoding id */
|
||||
PGVerbosity verbosity; /* error/notice message verbosity */
|
||||
pgParameterStatus *pstatus; /* ParameterStatus data */
|
||||
int client_encoding; /* encoding id */
|
||||
PGVerbosity verbosity; /* error/notice message verbosity */
|
||||
PGlobjfuncs *lobjfuncs; /* private state for large-object access
|
||||
* fns */
|
||||
|
||||
@@ -309,8 +310,8 @@ struct pg_conn
|
||||
int outCount; /* number of chars waiting in buffer */
|
||||
|
||||
/* State for constructing messages in outBuffer */
|
||||
int outMsgStart; /* offset to msg start (length word);
|
||||
* if -1, msg has no length word */
|
||||
int outMsgStart; /* offset to msg start (length word); if
|
||||
* -1, msg has no length word */
|
||||
int outMsgEnd; /* offset to msg end (so far) */
|
||||
|
||||
/* Status for asynchronous result construction */
|
||||
@@ -350,8 +351,8 @@ extern char *const pgresStatus[];
|
||||
|
||||
/* === in fe-connect.c === */
|
||||
|
||||
extern int pqPacketSend(PGconn *conn, char pack_type,
|
||||
const void *buf, size_t buf_len);
|
||||
extern int pqPacketSend(PGconn *conn, char pack_type,
|
||||
const void *buf, size_t buf_len);
|
||||
|
||||
/* === in fe-exec.c === */
|
||||
|
||||
@@ -362,14 +363,15 @@ extern char *pqResultStrdup(PGresult *res, const char *str);
|
||||
extern void pqClearAsyncResult(PGconn *conn);
|
||||
extern void pqSaveErrorResult(PGconn *conn);
|
||||
extern PGresult *pqPrepareAsyncResult(PGconn *conn);
|
||||
extern void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt, ...)
|
||||
extern void
|
||||
pqInternalNotice(const PGNoticeHooks * hooks, const char *fmt,...)
|
||||
/* This lets gcc check the format string for consistency. */
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
extern int pqAddTuple(PGresult *res, PGresAttValue *tup);
|
||||
extern int pqAddTuple(PGresult *res, PGresAttValue * tup);
|
||||
extern void pqSaveMessageField(PGresult *res, char code,
|
||||
const char *value);
|
||||
const char *value);
|
||||
extern void pqSaveParameterStatus(PGconn *conn, const char *name,
|
||||
const char *value);
|
||||
const char *value);
|
||||
extern void pqHandleSendFailure(PGconn *conn);
|
||||
|
||||
/* === in fe-protocol2.c === */
|
||||
@@ -377,21 +379,21 @@ extern void pqHandleSendFailure(PGconn *conn);
|
||||
extern PostgresPollingStatusType pqSetenvPoll(PGconn *conn);
|
||||
|
||||
extern char *pqBuildStartupPacket2(PGconn *conn, int *packetlen,
|
||||
const PQEnvironmentOption *options);
|
||||
const PQEnvironmentOption * options);
|
||||
extern void pqParseInput2(PGconn *conn);
|
||||
extern int pqGetCopyData2(PGconn *conn, char **buffer, int async);
|
||||
extern int pqGetline2(PGconn *conn, char *s, int maxlen);
|
||||
extern int pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
|
||||
extern int pqEndcopy2(PGconn *conn);
|
||||
extern PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
int *result_buf, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
int *result_buf, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
|
||||
/* === in fe-protocol3.c === */
|
||||
|
||||
extern char *pqBuildStartupPacket3(PGconn *conn, int *packetlen,
|
||||
const PQEnvironmentOption *options);
|
||||
const PQEnvironmentOption * options);
|
||||
extern void pqParseInput3(PGconn *conn);
|
||||
extern int pqGetErrorNotice3(PGconn *conn, bool isError);
|
||||
extern int pqGetCopyData3(PGconn *conn, char **buffer, int async);
|
||||
@@ -399,9 +401,9 @@ extern int pqGetline3(PGconn *conn, char *s, int maxlen);
|
||||
extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
|
||||
extern int pqEndcopy3(PGconn *conn);
|
||||
extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
int *result_buf, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
int *result_buf, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
|
||||
/* === in fe-misc.c === */
|
||||
|
||||
@@ -425,8 +427,8 @@ extern int pqPutMsgEnd(PGconn *conn);
|
||||
extern int pqReadData(PGconn *conn);
|
||||
extern int pqFlush(PGconn *conn);
|
||||
extern int pqWait(int forRead, int forWrite, PGconn *conn);
|
||||
extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
|
||||
time_t finish_time);
|
||||
extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
|
||||
time_t finish_time);
|
||||
extern int pqReadReady(PGconn *conn);
|
||||
extern int pqWriteReady(PGconn *conn);
|
||||
|
||||
|
Reference in New Issue
Block a user