|
|
|
/* src/interfaces/ecpg/ecpglib/ecpglib_extern.h */
|
|
|
|
|
|
|
|
#ifndef _ECPG_ECPGLIB_EXTERN_H
|
|
|
|
#define _ECPG_ECPGLIB_EXTERN_H
|
|
|
|
|
|
|
|
#include "libpq-fe.h"
|
|
|
|
#include "sqlca.h"
|
|
|
|
#include "sqlda-native.h"
|
|
|
|
#include "sqlda-compat.h"
|
|
|
|
#include "ecpg_config.h"
|
|
|
|
|
|
|
|
#ifndef CHAR_BIT
|
|
|
|
#include <limits.h>
|
|
|
|
#endif
|
Avoid thread-safety problem in ecpglib.
ecpglib attempts to force the LC_NUMERIC locale to "C" while reading
server output, to avoid problems with strtod() and related functions.
Historically it's just issued setlocale() calls to do that, but that
has major problems if we're in a threaded application. setlocale()
itself is not required by POSIX to be thread-safe (and indeed is not,
on recent OpenBSD). Moreover, its effects are process-wide, so that
we could cause unexpected results in other threads, or another thread
could change our setting.
On platforms having uselocale(), which is required by POSIX:2008,
we can avoid these problems by using uselocale() instead. Windows
goes its own way as usual, but we can make it safe by using
_configthreadlocale(). Platforms having neither continue to use the
old code, but that should be pretty much nobody among current systems.
This should get back-patched, but let's see what the buildfarm
thinks of it first.
Michael Meskes and Tom Lane; thanks also to Takayuki Tsunakawa.
Discussion: https://postgr.es/m/31420.1547783697@sss.pgh.pa.us
7 years ago
|
|
|
#ifdef LOCALE_T_IN_XLOCALE
|
|
|
|
#include <xlocale.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
enum COMPAT_MODE
|
|
|
|
{
|
|
|
|
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE
|
|
|
|
};
|
|
|
|
|
|
|
|
extern bool ecpg_internal_regression_mode;
|
|
|
|
|
|
|
|
#define INFORMIX_MODE(X) ((X) == ECPG_COMPAT_INFORMIX || (X) == ECPG_COMPAT_INFORMIX_SE)
|
|
|
|
#define ORACLE_MODE(X) ((X) == ECPG_COMPAT_ORACLE)
|
|
|
|
|
|
|
|
enum ARRAY_TYPE
|
|
|
|
{
|
|
|
|
ECPG_ARRAY_ERROR, ECPG_ARRAY_NOT_SET, ECPG_ARRAY_ARRAY, ECPG_ARRAY_VECTOR, ECPG_ARRAY_NONE
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ECPG_IS_ARRAY(X) ((X) == ECPG_ARRAY_ARRAY || (X) == ECPG_ARRAY_VECTOR)
|
|
|
|
|
|
|
|
/* A generic varchar type. */
|
|
|
|
struct ECPGgeneric_varchar
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char arr[FLEXIBLE_ARRAY_MEMBER];
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* type information cache
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct ECPGtype_information_cache
|
|
|
|
{
|
|
|
|
struct ECPGtype_information_cache *next;
|
|
|
|
int oid;
|
|
|
|
enum ARRAY_TYPE isarray;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* structure to store one statement */
|
|
|
|
struct statement
|
|
|
|
{
|
|
|
|
int lineno;
|
|
|
|
char *command;
|
|
|
|
char *name;
|
|
|
|
struct connection *connection;
|
|
|
|
enum COMPAT_MODE compat;
|
|
|
|
bool force_indicator;
|
|
|
|
enum ECPG_statement_type statement_type;
|
|
|
|
bool questionmarks;
|
|
|
|
struct variable *inlist;
|
|
|
|
struct variable *outlist;
|
Avoid thread-safety problem in ecpglib.
ecpglib attempts to force the LC_NUMERIC locale to "C" while reading
server output, to avoid problems with strtod() and related functions.
Historically it's just issued setlocale() calls to do that, but that
has major problems if we're in a threaded application. setlocale()
itself is not required by POSIX to be thread-safe (and indeed is not,
on recent OpenBSD). Moreover, its effects are process-wide, so that
we could cause unexpected results in other threads, or another thread
could change our setting.
On platforms having uselocale(), which is required by POSIX:2008,
we can avoid these problems by using uselocale() instead. Windows
goes its own way as usual, but we can make it safe by using
_configthreadlocale(). Platforms having neither continue to use the
old code, but that should be pretty much nobody among current systems.
This should get back-patched, but let's see what the buildfarm
thinks of it first.
Michael Meskes and Tom Lane; thanks also to Takayuki Tsunakawa.
Discussion: https://postgr.es/m/31420.1547783697@sss.pgh.pa.us
7 years ago
|
|
|
#ifdef HAVE_USELOCALE
|
|
|
|
locale_t clocale;
|
|
|
|
locale_t oldlocale;
|
|
|
|
#else
|
|
|
|
char *oldlocale;
|
|
|
|
#ifdef HAVE__CONFIGTHREADLOCALE
|
Avoid thread-safety problem in ecpglib.
ecpglib attempts to force the LC_NUMERIC locale to "C" while reading
server output, to avoid problems with strtod() and related functions.
Historically it's just issued setlocale() calls to do that, but that
has major problems if we're in a threaded application. setlocale()
itself is not required by POSIX to be thread-safe (and indeed is not,
on recent OpenBSD). Moreover, its effects are process-wide, so that
we could cause unexpected results in other threads, or another thread
could change our setting.
On platforms having uselocale(), which is required by POSIX:2008,
we can avoid these problems by using uselocale() instead. Windows
goes its own way as usual, but we can make it safe by using
_configthreadlocale(). Platforms having neither continue to use the
old code, but that should be pretty much nobody among current systems.
This should get back-patched, but let's see what the buildfarm
thinks of it first.
Michael Meskes and Tom Lane; thanks also to Takayuki Tsunakawa.
Discussion: https://postgr.es/m/31420.1547783697@sss.pgh.pa.us
7 years ago
|
|
|
int oldthreadlocale;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
int nparams;
|
|
|
|
char **paramvalues;
|
|
|
|
PGresult *results;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* structure to store prepared statements for a connection */
|
|
|
|
struct prepared_statement
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
bool prepared;
|
|
|
|
struct statement *stmt;
|
|
|
|
struct prepared_statement *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* structure to store connections */
|
|
|
|
struct connection
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
PGconn *connection;
|
|
|
|
bool autocommit;
|
|
|
|
struct ECPGtype_information_cache *cache_head;
|
|
|
|
struct prepared_statement *prep_stmts;
|
|
|
|
struct connection *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* structure to store descriptors */
|
|
|
|
struct descriptor
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
PGresult *result;
|
|
|
|
struct descriptor *next;
|
|
|
|
int count;
|
|
|
|
struct descriptor_item *items;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct descriptor_item
|
|
|
|
{
|
|
|
|
int num;
|
|
|
|
char *data;
|
|
|
|
int indicator;
|
|
|
|
int length;
|
|
|
|
int precision;
|
|
|
|
int scale;
|
|
|
|
int type;
|
|
|
|
struct descriptor_item *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct variable
|
|
|
|
{
|
|
|
|
enum ECPGttype type;
|
|
|
|
void *value;
|
|
|
|
void *pointer;
|
|
|
|
long varcharsize;
|
|
|
|
long arrsize;
|
|
|
|
long offset;
|
|
|
|
enum ECPGttype ind_type;
|
|
|
|
void *ind_value;
|
|
|
|
void *ind_pointer;
|
|
|
|
long ind_varcharsize;
|
|
|
|
long ind_arrsize;
|
|
|
|
long ind_offset;
|
|
|
|
struct variable *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct var_list
|
|
|
|
{
|
|
|
|
int number;
|
|
|
|
void *pointer;
|
|
|
|
struct var_list *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern struct var_list *ivlist;
|
|
|
|
|
|
|
|
/* Here are some methods used by the lib. */
|
|
|
|
|
|
|
|
bool ecpg_add_mem(void *ptr, int lineno);
|
|
|
|
|
|
|
|
bool ecpg_get_data(const PGresult *, int, int, int, enum ECPGttype type,
|
|
|
|
enum ECPGttype, char *, char *, long, long, long,
|
|
|
|
enum ARRAY_TYPE, enum COMPAT_MODE, bool);
|
|
|
|
|
|
|
|
#ifdef ENABLE_THREAD_SAFETY
|
|
|
|
void ecpg_pthreads_init(void);
|
|
|
|
#endif
|
|
|
|
struct connection *ecpg_get_connection(const char *);
|
|
|
|
char *ecpg_alloc(long, int);
|
|
|
|
char *ecpg_auto_alloc(long, int);
|
|
|
|
char *ecpg_realloc(void *, long, int);
|
|
|
|
void ecpg_free(void *);
|
|
|
|
bool ecpg_init(const struct connection *, const char *, const int);
|
|
|
|
char *ecpg_strdup(const char *, int);
|
|
|
|
const char *ecpg_type_name(enum ECPGttype);
|
|
|
|
int ecpg_dynamic_type(Oid);
|
|
|
|
int sqlda_dynamic_type(Oid, enum COMPAT_MODE);
|
|
|
|
void ecpg_free_auto_mem(void);
|
|
|
|
void ecpg_clear_auto_mem(void);
|
|
|
|
|
|
|
|
struct descriptor *ecpggetdescp(int, char *);
|
|
|
|
|
|
|
|
struct descriptor *ecpg_find_desc(int line, const char *name);
|
|
|
|
|
|
|
|
struct prepared_statement *ecpg_find_prepared_statement(const char *,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
8 years ago
|
|
|
struct connection *, struct prepared_statement **);
|
|
|
|
|
|
|
|
bool ecpg_store_result(const PGresult *results, int act_field,
|
|
|
|
const struct statement *stmt, struct variable *var);
|
|
|
|
bool ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
|
|
|
|
void ecpg_free_params(struct statement *stmt, bool print);
|
|
|
|
bool ecpg_do_prologue(int, const int, const int, const char *, const bool,
|
|
|
|
enum ECPG_statement_type, const char *, va_list,
|
|
|
|
struct statement **);
|
|
|
|
bool ecpg_build_params(struct statement *);
|
|
|
|
bool ecpg_autostart_transaction(struct statement *stmt);
|
|
|
|
bool ecpg_execute(struct statement *stmt);
|
|
|
|
bool ecpg_process_output(struct statement *, bool);
|
|
|
|
void ecpg_do_epilogue(struct statement *);
|
|
|
|
bool ecpg_do(const int, const int, const int, const char *, const bool,
|
|
|
|
const int, const char *, va_list);
|
|
|
|
|
|
|
|
bool ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE);
|
|
|
|
void ecpg_raise(int line, int code, const char *sqlstate, const char *str);
|
|
|
|
void ecpg_raise_backend(int line, PGresult *result, PGconn *conn, int compat);
|
|
|
|
char *ecpg_prepared(const char *, struct connection *);
|
|
|
|
bool ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *conn);
|
|
|
|
void ecpg_log(const char *format,...) pg_attribute_printf(1, 2);
|
|
|
|
bool ecpg_auto_prepare(int, const char *, const int, char **, const char *);
|
|
|
|
void ecpg_init_sqlca(struct sqlca_t *sqlca);
|
|
|
|
|
|
|
|
struct sqlda_compat *ecpg_build_compat_sqlda(int, PGresult *, int, enum COMPAT_MODE);
|
|
|
|
void ecpg_set_compat_sqlda(int, struct sqlda_compat **, const PGresult *, int, enum COMPAT_MODE);
|
|
|
|
struct sqlda_struct *ecpg_build_native_sqlda(int, PGresult *, int, enum COMPAT_MODE);
|
|
|
|
void ecpg_set_native_sqlda(int, struct sqlda_struct **, const PGresult *, int, enum COMPAT_MODE);
|
|
|
|
|
|
|
|
/* SQLSTATE values generated or processed by ecpglib (intentionally
|
|
|
|
* not exported -- users should refer to the codes directly) */
|
|
|
|
|
|
|
|
#define ECPG_SQLSTATE_NO_DATA "02000"
|
|
|
|
#define ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS "07001"
|
|
|
|
#define ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_TARGETS "07002"
|
|
|
|
#define ECPG_SQLSTATE_RESTRICTED_DATA_TYPE_ATTRIBUTE_VIOLATION "07006"
|
|
|
|
#define ECPG_SQLSTATE_INVALID_DESCRIPTOR_INDEX "07009"
|
|
|
|
#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_NULL_VALUE_NO_INDICATOR_PARAMETER "22002"
|
|
|
|
#define ECPG_SQLSTATE_ACTIVE_SQL_TRANSACTION "25001"
|
|
|
|
#define ECPG_SQLSTATE_NO_ACTIVE_SQL_TRANSACTION "25P01"
|
|
|
|
#define ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME "26000"
|
|
|
|
#define ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME "33000"
|
|
|
|
#define ECPG_SQLSTATE_INVALID_CURSOR_NAME "34000"
|
|
|
|
#define ECPG_SQLSTATE_SYNTAX_ERROR "42601"
|
|
|
|
#define ECPG_SQLSTATE_DATATYPE_MISMATCH "42804"
|
|
|
|
#define ECPG_SQLSTATE_DUPLICATE_CURSOR "42P03"
|
|
|
|
|
|
|
|
/* implementation-defined internal errors of ecpg */
|
|
|
|
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR "YE000"
|
|
|
|
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY "YE001"
|
|
|
|
|
|
|
|
#endif /* _ECPG_ECPGLIB_EXTERN_H */
|