Commit 99d21d5b authored by Byron Nikolaidis's avatar Byron Nikolaidis

Update odbc driver to current version V.0244

parent 85f91d0e
/* Module: bind.c /* Module: bind.c
* *
* Description: This module contains routines related to binding * Description: This module contains routines related to binding
* columns and parameters. * columns and parameters.
* *
* Classes: BindInfoClass, ParameterInfoClass * Classes: BindInfoClass, ParameterInfoClass
* *
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams, * API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
* SQLParamOptions(NI) * SQLParamOptions(NI)
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include "bind.h" #include "bind.h"
#include "environ.h" #include "environ.h"
#include "statement.h" #include "statement.h"
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "pgtypes.h" #include "pgtypes.h"
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
#include <sql.h> #include <sql.h>
#include <sqlext.h> #include <sqlext.h>
// Bind parameters on a statement handle // Bind parameters on a statement handle
...@@ -77,10 +77,11 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -77,10 +77,11 @@ StatementClass *stmt = (StatementClass *) hstmt;
stmt->parameters[i].CType = 0; stmt->parameters[i].CType = 0;
stmt->parameters[i].SQLType = 0; stmt->parameters[i].SQLType = 0;
stmt->parameters[i].precision = 0; stmt->parameters[i].precision = 0;
stmt->parameters[i].scale = 0; stmt->parameters[i].scale = 0;
stmt->parameters[i].data_at_exec = FALSE; stmt->parameters[i].data_at_exec = FALSE;
stmt->parameters[i].EXEC_used = NULL; stmt->parameters[i].lobj_oid = 0;
stmt->parameters[i].EXEC_buffer = NULL; stmt->parameters[i].EXEC_used = NULL;
stmt->parameters[i].EXEC_buffer = NULL;
} }
} }
...@@ -94,26 +95,28 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -94,26 +95,28 @@ StatementClass *stmt = (StatementClass *) hstmt;
stmt->parameters[ipar].CType = fCType; stmt->parameters[ipar].CType = fCType;
stmt->parameters[ipar].SQLType = fSqlType; stmt->parameters[ipar].SQLType = fSqlType;
stmt->parameters[ipar].precision = cbColDef; stmt->parameters[ipar].precision = cbColDef;
stmt->parameters[ipar].scale = ibScale; stmt->parameters[ipar].scale = ibScale;
/* If rebinding a parameter that had data-at-exec stuff in it, /* If rebinding a parameter that had data-at-exec stuff in it,
then free that stuff then free that stuff
*/ */
if (stmt->parameters[ipar].EXEC_used) { if (stmt->parameters[ipar].EXEC_used) {
free(stmt->parameters[ipar].EXEC_used); free(stmt->parameters[ipar].EXEC_used);
stmt->parameters[ipar].EXEC_used = NULL; stmt->parameters[ipar].EXEC_used = NULL;
} }
if (stmt->parameters[ipar].EXEC_buffer) { if (stmt->parameters[ipar].EXEC_buffer) {
free(stmt->parameters[ipar].EXEC_buffer); free(stmt->parameters[ipar].EXEC_buffer);
stmt->parameters[ipar].EXEC_buffer = NULL; stmt->parameters[ipar].EXEC_buffer = NULL;
} }
if (pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET) if (pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
stmt->parameters[ipar].data_at_exec = TRUE; stmt->parameters[ipar].data_at_exec = TRUE;
else else
stmt->parameters[ipar].data_at_exec = FALSE; stmt->parameters[ipar].data_at_exec = FALSE;
mylog("SQLBindParamater: ipar = %d, *pcbValue = %d, data_at_exec = %d\n",
ipar, pcbValue ? *pcbValue: -777, stmt->parameters[ipar].data_at_exec);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -188,6 +191,8 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol); ...@@ -188,6 +191,8 @@ mylog("**** SQLBindCol: stmt = %u, icol = %d\n", stmt, icol);
stmt->bindings[icol].buffer = rgbValue; stmt->bindings[icol].buffer = rgbValue;
stmt->bindings[icol].used = pcbValue; stmt->bindings[icol].used = pcbValue;
stmt->bindings[icol].returntype = fCType; stmt->bindings[icol].returntype = fCType;
mylog(" bound buffer[%d] = %u\n", icol, stmt->bindings[icol].buffer);
} }
return SQL_SUCCESS; return SQL_SUCCESS;
...@@ -228,7 +233,7 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -228,7 +233,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
*pibScale = stmt->parameters[ipar].scale; *pibScale = stmt->parameters[ipar].scale;
if(pfNullable) if(pfNullable)
*pfNullable = pgtype_nullable(stmt->parameters[ipar].paramType); *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -247,37 +252,25 @@ RETCODE SQL_API SQLParamOptions( ...@@ -247,37 +252,25 @@ RETCODE SQL_API SQLParamOptions(
// - - - - - - - - - // - - - - - - - - -
// Returns the number of parameter markers. // Returns the number of parameters in an SQL statement
RETCODE SQL_API SQLNumParams( RETCODE SQL_API SQLNumParams(
HSTMT hstmt, HSTMT hstmt,
SWORD FAR *pcpar) SWORD FAR *pcpar)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
unsigned int i;
// I guess this is the number of actual parameter markers
// in the statement, not the number of parameters that are bound.
// why does this have to be driver-specific?
if(!stmt) if(!stmt)
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
if(!stmt->statement) { // If the statement does not have parameters, it should just return 0.
// no statement has been allocated
*pcpar = 0;
stmt->errormsg = "SQLNumParams called with no statement ready.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
return SQL_ERROR;
} else {
*pcpar = 0;
for(i=0; i < strlen(stmt->statement); i++) {
if(stmt->statement[i] == '?')
(*pcpar)++;
}
return SQL_SUCCESS; if (pcpar) {
*pcpar = stmt->parameters_allocated;
} }
return SQL_SUCCESS;
} }
/******************************************************************** /********************************************************************
...@@ -309,7 +302,7 @@ extend_bindings(StatementClass *stmt, int num_columns) ...@@ -309,7 +302,7 @@ extend_bindings(StatementClass *stmt, int num_columns)
BindInfoClass *new_bindings; BindInfoClass *new_bindings;
int i; int i;
mylog("in extend_bindings\n"); mylog("in extend_bindings: stmt=%u, bindings_allocated=%d, num_columns=%d\n", stmt, stmt->bindings_allocated, num_columns);
/* if we have too few, allocate room for more, and copy the old */ /* if we have too few, allocate room for more, and copy the old */
/* entries into the new structure */ /* entries into the new structure */
...@@ -325,6 +318,7 @@ int i; ...@@ -325,6 +318,7 @@ int i;
} }
stmt->bindings = new_bindings; // null indicates error stmt->bindings = new_bindings; // null indicates error
stmt->bindings_allocated = num_columns;
} else { } else {
/* if we have too many, make sure the extra ones are emptied out */ /* if we have too many, make sure the extra ones are emptied out */
......
/* File: bind.h /* File: bind.h
* *
* Description: See "bind.c" * Description: See "bind.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __BIND_H__ #ifndef __BIND_H__
#define __BIND_H__ #define __BIND_H__
#include "psqlodbc.h" #include "psqlodbc.h"
/* /*
* BindInfoClass -- stores information about a bound column * BindInfoClass -- stores information about a bound column
*/ */
struct BindInfoClass_ { struct BindInfoClass_ {
Int4 buflen; /* size of buffer */ Int4 buflen; /* size of buffer */
char *buffer; /* pointer to the buffer */ char *buffer; /* pointer to the buffer */
...@@ -33,10 +33,11 @@ struct ParameterInfoClass_ { ...@@ -33,10 +33,11 @@ struct ParameterInfoClass_ {
Int2 CType; Int2 CType;
Int2 SQLType; Int2 SQLType;
UInt4 precision; UInt4 precision;
Int2 scale; Int2 scale;
Int4 *EXEC_used; Oid lobj_oid;
char *EXEC_buffer; Int4 *EXEC_used; /* amount of data OR the oid of the large object */
char data_at_exec; char *EXEC_buffer; /* the data or the FD of the large object */
char data_at_exec;
}; };
BindInfoClass *create_empty_bindings(int num_columns); BindInfoClass *create_empty_bindings(int num_columns);
......
/* Module: columninfo.c /* Module: columninfo.c
* *
* Description: This module contains routines related to * Description: This module contains routines related to
* reading and storing the field information from a query. * reading and storing the field information from a query.
* *
* Classes: ColumnInfoClass (Functions prefix: "CI_") * Classes: ColumnInfoClass (Functions prefix: "CI_")
* *
* API functions: none * API functions: none
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include "columninfo.h" #include "columninfo.h"
#include "socket.h" #include "socket.h"
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
...@@ -29,6 +29,7 @@ ColumnInfoClass *rv; ...@@ -29,6 +29,7 @@ ColumnInfoClass *rv;
rv->name = NULL; rv->name = NULL;
rv->adtid = NULL; rv->adtid = NULL;
rv->adtsize = NULL; rv->adtsize = NULL;
rv->display_size = NULL;
} }
return rv; return rv;
...@@ -54,7 +55,7 @@ int new_num_fields; ...@@ -54,7 +55,7 @@ int new_num_fields;
Oid new_adtid; Oid new_adtid;
Int2 new_adtsize; Int2 new_adtsize;
char new_field_name[MAX_MESSAGE_LEN+1]; char new_field_name[MAX_MESSAGE_LEN+1];
/* at first read in the number of fields that are in the query */ /* at first read in the number of fields that are in the query */
new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2)); new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2));
...@@ -93,11 +94,12 @@ int num_fields = self->num_fields; ...@@ -93,11 +94,12 @@ int num_fields = self->num_fields;
if( self->name[lf]) if( self->name[lf])
free (self->name[lf]); free (self->name[lf]);
} }
/* Safe to call even if null */ /* Safe to call even if null */
free(self->name); free(self->name);
free(self->adtid); free(self->adtid);
free(self->adtsize); free(self->adtsize);
free(self->display_size);
} }
void void
...@@ -110,6 +112,7 @@ CI_set_num_fields(ColumnInfoClass *self, int new_num_fields) ...@@ -110,6 +112,7 @@ CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
self->name = (char **) malloc (sizeof(char *) * self->num_fields); self->name = (char **) malloc (sizeof(char *) * self->num_fields);
self->adtid = (Oid *) malloc (sizeof(Oid) * self->num_fields); self->adtid = (Oid *) malloc (sizeof(Oid) * self->num_fields);
self->adtsize = (Int2 *) malloc (sizeof(Int2) * self->num_fields); self->adtsize = (Int2 *) malloc (sizeof(Int2) * self->num_fields);
self->display_size = (Int2 *) malloc(sizeof(Int2) * self->num_fields);
} }
void void
...@@ -126,34 +129,7 @@ CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, ...@@ -126,34 +129,7 @@ CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
self->name[field_num] = strdup(new_name); self->name[field_num] = strdup(new_name);
self->adtid[field_num] = new_adtid; self->adtid[field_num] = new_adtid;
self->adtsize[field_num] = new_adtsize; self->adtsize[field_num] = new_adtsize;
}
char * self->display_size[field_num] = 0;
CI_get_fieldname(ColumnInfoClass *self, Int2 which)
{
char *rv = NULL;
if ( ! self->name)
return NULL;
if ((which >= 0) && (which < self->num_fields))
rv = self->name[which];
return rv;
}
Int2
CI_get_fieldsize(ColumnInfoClass *self, Int2 which)
{
Int2 rv = 0;
if ( ! self->adtsize)
return 0;
if ((which >= 0) && (which < self->num_fields))
rv = self->adtsize[which];
return rv;
} }
/* File: columninfo.h /* File: columninfo.h
* *
* Description: See "columninfo.c" * Description: See "columninfo.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __COLUMNINFO_H__ #ifndef __COLUMNINFO_H__
#define __COLUMNINFO_H__ #define __COLUMNINFO_H__
...@@ -17,14 +17,18 @@ struct ColumnInfoClass_ { ...@@ -17,14 +17,18 @@ struct ColumnInfoClass_ {
char **name; /* list of type names */ char **name; /* list of type names */
Oid *adtid; /* list of type ids */ Oid *adtid; /* list of type ids */
Int2 *adtsize; /* list type sizes */ Int2 *adtsize; /* list type sizes */
Int2 *display_size; /* the display size (longest row) */
}; };
#define CI_get_num_fields(self) (self->num_fields) #define CI_get_num_fields(self) (self->num_fields)
#define CI_get_oid(self, col) (self->adtid[col]) #define CI_get_oid(self, col) (self->adtid[col])
#define CI_get_fieldname(self, col) (self->name[col])
#define CI_get_fieldsize(self, col) (self->adtsize[col])
#define CI_get_display_size(self, col) (self->display_size[col])
ColumnInfoClass *CI_Constructor(); ColumnInfoClass *CI_Constructor();
void CI_Destructor(ColumnInfoClass *self); void CI_Destructor(ColumnInfoClass *self);
void CI_free_memory(ColumnInfoClass *self);
char CI_read_fields(ColumnInfoClass *self, SocketClass *sock); char CI_read_fields(ColumnInfoClass *self, SocketClass *sock);
/* functions for setting up the fields from within the program, */ /* functions for setting up the fields from within the program, */
...@@ -33,8 +37,5 @@ void CI_set_num_fields(ColumnInfoClass *self, int new_num_fields); ...@@ -33,8 +37,5 @@ void CI_set_num_fields(ColumnInfoClass *self, int new_num_fields);
void CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name, void CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
Oid new_adtid, Int2 new_adtsize); Oid new_adtid, Int2 new_adtsize);
char *CI_get_fieldname(ColumnInfoClass *self, Int2 which);
Int2 CI_get_fieldsize(ColumnInfoClass *self, Int2 which);
void CI_free_memory(ColumnInfoClass *self);
#endif #endif
This diff is collapsed.
/* File: connection.h /* File: connection.h
* *
* Description: See "connection.c" * Description: See "connection.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __CONNECTION_H__ #ifndef __CONNECTION_H__
#define __CONNECTION_H__ #define __CONNECTION_H__
#include <windows.h> #include <windows.h>
#include <sql.h> #include <sql.h>
#include <sqlext.h>
#include "psqlodbc.h" #include "psqlodbc.h"
typedef enum { typedef enum {
...@@ -44,9 +45,9 @@ typedef enum { ...@@ -44,9 +45,9 @@ typedef enum {
/* SetConnectOption: corresponds to ODBC--"S1009" */ /* SetConnectOption: corresponds to ODBC--"S1009" */
#define CONN_TRANSACT_IN_PROGRES 7 #define CONN_TRANSACT_IN_PROGRES 7
#define CONN_NO_MEMORY_ERROR 8 #define CONN_NO_MEMORY_ERROR 8
#define CONN_NOT_IMPLEMENTED_ERROR 9 #define CONN_NOT_IMPLEMENTED_ERROR 9
#define CONN_INVALID_AUTHENTICATION 10 #define CONN_INVALID_AUTHENTICATION 10
#define CONN_AUTH_TYPE_UNSUPPORTED 11 #define CONN_AUTH_TYPE_UNSUPPORTED 11
/* Conn_status defines */ /* Conn_status defines */
...@@ -77,12 +78,12 @@ typedef enum { ...@@ -77,12 +78,12 @@ typedef enum {
#define SM_OPTIONS 64 #define SM_OPTIONS 64
#define SM_UNUSED 64 #define SM_UNUSED 64
#define SM_TTY 64 #define SM_TTY 64
/* Old 6.2 protocol defines */ /* Old 6.2 protocol defines */
#define NO_AUTHENTICATION 7 #define NO_AUTHENTICATION 7
#define PATH_SIZE 64 #define PATH_SIZE 64
#define ARGV_SIZE 64 #define ARGV_SIZE 64
#define NAMEDATALEN 16 #define NAMEDATALEN 16
typedef unsigned int ProtocolVersion; typedef unsigned int ProtocolVersion;
...@@ -90,7 +91,7 @@ typedef unsigned int ProtocolVersion; ...@@ -90,7 +91,7 @@ typedef unsigned int ProtocolVersion;
#define PG_PROTOCOL_LATEST PG_PROTOCOL(1, 0) #define PG_PROTOCOL_LATEST PG_PROTOCOL(1, 0)
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(0, 0) #define PG_PROTOCOL_EARLIEST PG_PROTOCOL(0, 0)
/* This startup packet is to support latest Postgres protocol (6.3) */ /* This startup packet is to support latest Postgres protocol (6.3) */
typedef struct _StartupPacket typedef struct _StartupPacket
{ {
ProtocolVersion protoVersion; ProtocolVersion protoVersion;
...@@ -100,41 +101,47 @@ typedef struct _StartupPacket ...@@ -100,41 +101,47 @@ typedef struct _StartupPacket
char unused[SM_UNUSED]; char unused[SM_UNUSED];
char tty[SM_TTY]; char tty[SM_TTY];
} StartupPacket; } StartupPacket;
/* This startup packet is to support pre-Postgres 6.3 protocol */ /* This startup packet is to support pre-Postgres 6.3 protocol */
typedef struct _StartupPacket6_2 typedef struct _StartupPacket6_2
{ {
unsigned int authtype; unsigned int authtype;
char database[PATH_SIZE]; char database[PATH_SIZE];
char user[NAMEDATALEN]; char user[NAMEDATALEN];
char options[ARGV_SIZE]; char options[ARGV_SIZE];
char execfile[ARGV_SIZE]; char execfile[ARGV_SIZE];
char tty[PATH_SIZE]; char tty[PATH_SIZE];
} StartupPacket6_2; } StartupPacket6_2;
/* Structure to hold all the connection attributes for a specific /* Structure to hold all the connection attributes for a specific
connection (used for both registry and file, DSN and DRIVER) connection (used for both registry and file, DSN and DRIVER)
*/ */
typedef struct { typedef struct {
char dsn[MEDIUM_REGISTRY_LEN]; char dsn[MEDIUM_REGISTRY_LEN];
char desc[MEDIUM_REGISTRY_LEN];
char driver[MEDIUM_REGISTRY_LEN]; char driver[MEDIUM_REGISTRY_LEN];
char server[MEDIUM_REGISTRY_LEN]; char server[MEDIUM_REGISTRY_LEN];
char database[MEDIUM_REGISTRY_LEN]; char database[MEDIUM_REGISTRY_LEN];
char username[MEDIUM_REGISTRY_LEN]; char username[MEDIUM_REGISTRY_LEN];
char password[MEDIUM_REGISTRY_LEN]; char password[MEDIUM_REGISTRY_LEN];
char conn_settings[LARGE_REGISTRY_LEN]; char conn_settings[LARGE_REGISTRY_LEN];
char protocol[SMALL_REGISTRY_LEN]; char protocol[SMALL_REGISTRY_LEN];
char port[SMALL_REGISTRY_LEN]; char port[SMALL_REGISTRY_LEN];
char readonly[SMALL_REGISTRY_LEN]; char readonly[SMALL_REGISTRY_LEN];
// char unknown_sizes[SMALL_REGISTRY_LEN];
char fake_oid_index[SMALL_REGISTRY_LEN];
char show_oid_column[SMALL_REGISTRY_LEN];
char show_system_tables[SMALL_REGISTRY_LEN];
char focus_password; char focus_password;
} ConnInfo; } ConnInfo;
/* Macro to determine is the connection using 6.2 protocol? */ /* Macro to determine is the connection using 6.2 protocol? */
#define PROTOCOL_62(conninfo_) (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0) #define PROTOCOL_62(conninfo_) (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0)
/******* The Connection handle ************/ /******* The Connection handle ************/
struct ConnectionClass_ { struct ConnectionClass_ {
HENV henv; /* environment this connection was created on */ HENV henv; /* environment this connection was created on */
...@@ -145,6 +152,7 @@ struct ConnectionClass_ { ...@@ -145,6 +152,7 @@ struct ConnectionClass_ {
StatementClass **stmts; StatementClass **stmts;
int num_stmts; int num_stmts;
SocketClass *sock; SocketClass *sock;
int lobj_type;
char transact_status; /* Is a transaction is currently in progress */ char transact_status; /* Is a transaction is currently in progress */
char errormsg_created; /* has an informative error msg been created? */ char errormsg_created; /* has an informative error msg been created? */
}; };
...@@ -162,15 +170,14 @@ struct ConnectionClass_ { ...@@ -162,15 +170,14 @@ struct ConnectionClass_ {
/* for CC_DSN_info */ /* for CC_DSN_info */
#define CONN_DONT_OVERWRITE 0 #define CONN_DONT_OVERWRITE 0
#define CONN_OVERWRITE 1 #define CONN_OVERWRITE 1
/* prototypes */ /* prototypes */
ConnectionClass *CC_Constructor(); ConnectionClass *CC_Constructor();
char CC_Destructor(ConnectionClass *self); char CC_Destructor(ConnectionClass *self);
int CC_cursor_count(ConnectionClass *self);
char CC_cleanup(ConnectionClass *self); char CC_cleanup(ConnectionClass *self);
char CC_abort(ConnectionClass *self); char CC_abort(ConnectionClass *self);
void CC_DSN_info(ConnectionClass *self, char overwrite);
void CC_set_defaults(ConnectionClass *self);
char CC_connect(ConnectionClass *self, char do_password); char CC_connect(ConnectionClass *self, char do_password);
char CC_add_statement(ConnectionClass *self, StatementClass *stmt); char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt); char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
...@@ -178,6 +185,8 @@ char CC_get_error(ConnectionClass *self, int *number, char **message); ...@@ -178,6 +185,8 @@ char CC_get_error(ConnectionClass *self, int *number, char **message);
QResultClass *CC_send_query(ConnectionClass *self, char *query, QResultClass *result_in, char *cursor); QResultClass *CC_send_query(ConnectionClass *self, char *query, QResultClass *result_in, char *cursor);
void CC_clear_error(ConnectionClass *self); void CC_clear_error(ConnectionClass *self);
char *CC_create_errormsg(ConnectionClass *self); char *CC_create_errormsg(ConnectionClass *self);
char CC_send_settings(ConnectionClass *self); int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
char CC_send_settings(ConnectionClass *self);
void CC_lookup_lo(ConnectionClass *conn);
#endif #endif
This diff is collapsed.
/* File: convert.h /* File: convert.h
* *
* Description: See "convert.c" * Description: See "convert.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __CONVERT_H__ #ifndef __CONVERT_H__
#define __CONVERT_H__ #define __CONVERT_H__
...@@ -13,10 +13,12 @@ ...@@ -13,10 +13,12 @@
#include "psqlodbc.h" #include "psqlodbc.h"
/* copy_and_convert results */ /* copy_and_convert results */
#define COPY_OK 0 #define COPY_OK 0
#define COPY_UNSUPPORTED_TYPE 1 #define COPY_UNSUPPORTED_TYPE 1
#define COPY_UNSUPPORTED_CONVERSION 2 #define COPY_UNSUPPORTED_CONVERSION 2
#define COPY_RESULT_TRUNCATED 3 #define COPY_RESULT_TRUNCATED 3
#define COPY_GENERAL_ERROR 4
#define COPY_NO_DATA_FOUND 5
typedef struct { typedef struct {
int m; int m;
...@@ -27,21 +29,21 @@ typedef struct { ...@@ -27,21 +29,21 @@ typedef struct {
int ss; int ss;
} SIMPLE_TIME; } SIMPLE_TIME;
int copy_and_convert_field_bindinfo(Int4 field_type, void *value, BindInfoClass *bic); int copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col);
int copy_and_convert_field(Int4 field_type, void *value, int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
Int2 fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue); PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue, char multiple);
int copy_statement_with_parameters(StatementClass *stmt); int copy_statement_with_parameters(StatementClass *stmt);
char *convert_escape(char *value); char *convert_escape(char *value);
char *convert_money(char *s); char *convert_money(char *s);
int monthToNumber(char *mon);
char *convert_time(SIMPLE_TIME *st);
char parse_datetime(char *buf, SIMPLE_TIME *st); char parse_datetime(char *buf, SIMPLE_TIME *st);
char *convert_linefeeds(char *s, char *dst, size_t max); char *convert_linefeeds(char *s, char *dst, size_t max);
char *convert_returns(char *si, char *dst, int used); char *convert_special_chars(char *si, char *dst, int used);
int convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax); int convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax);
int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax); int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax);
int convert_to_pgbinary(unsigned char *in, char *out, int len); int convert_to_pgbinary(unsigned char *in, char *out, int len);
int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
SDWORD cbValueMax, SDWORD *pcbValue, char multiple);
#endif #endif
This diff is collapsed.
/* File: dlg_specific.h
*
* Description: See "dlg_specific.c"
*
* Comments: See "notice.txt" for copyright and license information.
*
*/
#ifndef __DLG_SPECIFIC_H__
#define __DLG_SPECIFIC_H__
#include "psqlodbc.h"
#include "connection.h"
#include <windows.h>
#include <windowsx.h>
#include <odbcinst.h>
#include "resource.h"
/* Unknown data type sizes */
#define UNKNOWNS_AS_MAX 0
#define UNKNOWNS_AS_DONTKNOW 1
#define UNKNOWNS_AS_LONGEST 2
/* INI File Stuff */
#define ODBC_INI "ODBC.INI" /* ODBC initialization file */
#define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */
#define INI_KDESC "Description" /* Data source description */
#define INI_SERVER "Servername" /* Name of Server running the Postgres service */
#define INI_PORT "Port" /* Port on which the Postmaster is listening */
#define INI_DATABASE "Database" /* Database Name */
#define INI_USER "Username" /* Default User Name */
#define INI_PASSWORD "Password" /* Default Password */
#define INI_DEBUG "Debug" /* Debug flag */
#define INI_FETCH "Fetch" /* Fetch Max Count */
#define INI_SOCKET "Socket" /* Socket buffer size */
#define INI_READONLY "ReadOnly" /* Database is read only */
#define INI_COMMLOG "CommLog" /* Communication to backend logging */
#define INI_PROTOCOL "Protocol" /* What protocol (6.2) */
#define INI_OPTIMIZER "Optimizer" /* Use backend genetic optimizer */
#define INI_CONNSETTINGS "ConnSettings" /* Anything to send to backend on successful connection */
#define INI_UNIQUEINDEX "UniqueIndex" /* Recognize unique indexes */
#define INI_UNKNOWNSIZES "UnknownSizes" /* How to handle unknown result set sizes */
#define INI_USEDECLAREFETCH "UseDeclareFetch" /* Use Declare/Fetch cursors */
/* More ini stuff */
#define INI_TEXTASLONGVARCHAR "TextAsLongVarchar"
#define INI_UNKNOWNSASLONGVARCHAR "UnknownsAsLongVarchar"
#define INI_BOOLSASCHAR "BoolsAsChar"
#define INI_MAXVARCHARSIZE "MaxVarcharSize"
#define INI_MAXLONGVARCHARSIZE "MaxLongVarcharSize"
#define INI_FAKEOIDINDEX "FakeOidIndex"
#define INI_SHOWOIDCOLUMN "ShowOidColumn"
#define INI_SHOWSYSTEMTABLES "ShowSystemTables"
#define INI_EXTRASYSTABLEPREFIXES "ExtraSysTablePrefixes"
/* Connection Defaults */
#define DEFAULT_PORT "5432"
#define DEFAULT_READONLY 1
#define DEFAULT_USEDECLAREFETCH 1
#define DEFAULT_TEXTASLONGVARCHAR 1
#define DEFAULT_UNKNOWNSASLONGVARCHAR 0
#define DEFAULT_BOOLSASCHAR 1
#define DEFAULT_OPTIMIZER 1 // disable
#define DEFAULT_UNIQUEINDEX 0 // dont recognize
#define DEFAULT_COMMLOG 0 // dont log
#define DEFAULT_UNKNOWNSIZES UNKNOWNS_AS_MAX
#define DEFAULT_FAKEOIDINDEX 0
#define DEFAULT_SHOWOIDCOLUMN 0
#define DEFAULT_SHOWSYSTEMTABLES 0 // dont show system tables
#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;"
/* prototypes */
void updateGlobals(void);
void getGlobalDefaults(void);
void SetDlgStuff(HWND hdlg, ConnInfo *ci);
void GetDlgStuff(HWND hdlg, ConnInfo *ci);
int CALLBACK driver_optionsProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam);
int CALLBACK ds_optionsProc(HWND hdlg,
WORD wMsg,
WPARAM wParam,
LPARAM lParam);
void makeConnectString(char *connect_string, ConnInfo *ci);
void copyAttributes(ConnInfo *ci, char *attribute, char *value);
void getDSNdefaults(ConnInfo *ci);
void getDSNinfo(ConnInfo *ci, char overwrite);
void writeDSNinfo(ConnInfo *ci);
#endif
/* Module: drvconn.c /* Module: drvconn.c
* *
* Description: This module contains only routines related to * Description: This module contains only routines related to
* implementing SQLDriverConnect. * implementing SQLDriverConnect.
* *
* Classes: n/a * Classes: n/a
* *
* API functions: SQLDriverConnect * API functions: SQLDriverConnect
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -26,15 +26,17 @@ ...@@ -26,15 +26,17 @@
#include <odbcinst.h> #include <odbcinst.h>
#include "resource.h" #include "resource.h"
#include "dlg_specific.h"
/* prototypes */ /* prototypes */
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam); BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci); RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci); void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */ extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
RETCODE SQL_API SQLDriverConnect( RETCODE SQL_API SQLDriverConnect(
HDBC hdbc, HDBC hdbc,
HWND hwnd, HWND hwnd,
...@@ -67,10 +69,10 @@ char password_required = FALSE; ...@@ -67,10 +69,10 @@ char password_required = FALSE;
// If the ConnInfo in the hdbc is missing anything, // If the ConnInfo in the hdbc is missing anything,
// this function will fill them in from the registry (assuming // this function will fill them in from the registry (assuming
// of course there is a DSN given -- if not, it does nothing!) // of course there is a DSN given -- if not, it does nothing!)
CC_DSN_info(conn, CONN_DONT_OVERWRITE); getDSNinfo(ci, CONN_DONT_OVERWRITE);
// Fill in any default parameters if they are not there. // Fill in any default parameters if they are not there.
CC_set_defaults(conn); getDSNdefaults(ci);
dialog: dialog:
ci->focus_password = password_required; ci->focus_password = password_required;
...@@ -102,14 +104,14 @@ dialog: ...@@ -102,14 +104,14 @@ dialog:
break; break;
} }
/* Password is not a required parameter unless authentication asks for it. /* Password is not a required parameter unless authentication asks for it.
For now, I think its better to just let the application ask over and over until For now, I think its better to just let the application ask over and over until
a password is entered (the user can always hit Cancel to get out) a password is entered (the user can always hit Cancel to get out)
*/ */
if( ci->username[0] == '\0' || if( ci->username[0] == '\0' ||
ci->server[0] == '\0' || ci->server[0] == '\0' ||
ci->database[0] == '\0' || ci->database[0] == '\0' ||
ci->port[0] == '\0') { ci->port[0] == '\0') {
// (password_required && ci->password[0] == '\0')) // (password_required && ci->password[0] == '\0'))
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
...@@ -119,19 +121,7 @@ dialog: ...@@ -119,19 +121,7 @@ dialog:
// return the completed string to the caller. // return the completed string to the caller.
char got_dsn = (ci->dsn[0] != '\0'); makeConnectString(connect_string, ci);
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;READONLY=%s;PWD=%s;PROTOCOL=%s;CONNSETTINGS=%s",
got_dsn ? "DSN" : "DRIVER",
got_dsn ? ci->dsn : ci->driver,
ci->database,
ci->server,
ci->port,
ci->username,
ci->readonly,
ci->password,
ci->protocol,
ci->conn_settings);
if(pcbConnStrOut) { if(pcbConnStrOut) {
*pcbConnStrOut = strlen(connect_string); *pcbConnStrOut = strlen(connect_string);
...@@ -169,7 +159,7 @@ int dialog_result; ...@@ -169,7 +159,7 @@ int dialog_result;
mylog("dconn_DoDialog: ci = %u\n", ci); mylog("dconn_DoDialog: ci = %u\n", ci);
if(hwnd) { if(hwnd) {
dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DRIVERCONNDIALOG), dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG),
hwnd, dconn_FDriverConnectProc, (LPARAM) ci); hwnd, dconn_FDriverConnectProc, (LPARAM) ci);
if(!dialog_result || (dialog_result == -1)) { if(!dialog_result || (dialog_result == -1)) {
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
...@@ -188,34 +178,37 @@ BOOL FAR PASCAL dconn_FDriverConnectProc( ...@@ -188,34 +178,37 @@ BOOL FAR PASCAL dconn_FDriverConnectProc(
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
static ConnInfo *ci; ConnInfo *ci;
switch (wMsg) { switch (wMsg) {
case WM_INITDIALOG: case WM_INITDIALOG:
ci = (ConnInfo *) lParam; // Save the ConnInfo for the "OK" ci = (ConnInfo *) lParam;
SetDlgItemText(hdlg, SERVER_EDIT, ci->server); /* Change the caption for the setup dialog */
SetDlgItemText(hdlg, DATABASE_EDIT, ci->database); SetWindowText(hdlg, "PostgreSQL Connection");
SetDlgItemText(hdlg, USERNAME_EDIT, ci->username);
SetDlgItemText(hdlg, PASSWORD_EDIT, ci->password); SetWindowText(GetDlgItem(hdlg, IDC_DATASOURCE), "Connection");
SetDlgItemText(hdlg, PORT_EDIT, ci->port);
CheckDlgButton(hdlg, READONLY_EDIT, atoi(ci->readonly)); /* Hide the DSN and description fields */
ShowWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), SW_HIDE);
CheckDlgButton(hdlg, PG62_EDIT, PROTOCOL_62(ci)); ShowWindow(GetDlgItem(hdlg, IDC_DSNAME), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
/* The driver connect dialog box allows manipulating this global variable */ ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
CheckDlgButton(hdlg, COMMLOG_EDIT, globals.commlog);
SetWindowLong(hdlg, DWL_USER, lParam);// Save the ConnInfo for the "OK"
SetDlgStuff(hdlg, ci);
if (ci->database[0] == '\0') if (ci->database[0] == '\0')
; /* default focus */ ; /* default focus */
else if (ci->server[0] == '\0') else if (ci->server[0] == '\0')
SetFocus(GetDlgItem(hdlg, SERVER_EDIT)); SetFocus(GetDlgItem(hdlg, IDC_SERVER));
else if (ci->port[0] == '\0') else if (ci->port[0] == '\0')
SetFocus(GetDlgItem(hdlg, PORT_EDIT)); SetFocus(GetDlgItem(hdlg, IDC_PORT));
else if (ci->username[0] == '\0') else if (ci->username[0] == '\0')
SetFocus(GetDlgItem(hdlg, USERNAME_EDIT)); SetFocus(GetDlgItem(hdlg, IDC_USER));
else if (ci->focus_password) else if (ci->focus_password)
SetFocus(GetDlgItem(hdlg, PASSWORD_EDIT)); SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
break; break;
...@@ -223,26 +216,30 @@ static ConnInfo *ci; ...@@ -223,26 +216,30 @@ static ConnInfo *ci;
switch (GET_WM_COMMAND_ID(wParam, lParam)) { switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDOK: case IDOK:
GetDlgItemText(hdlg, SERVER_EDIT, ci->server, sizeof(ci->server)); ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
GetDlgItemText(hdlg, DATABASE_EDIT, ci->database, sizeof(ci->database));
GetDlgItemText(hdlg, USERNAME_EDIT, ci->username, sizeof(ci->username)); GetDlgStuff(hdlg, ci);
GetDlgItemText(hdlg, PASSWORD_EDIT, ci->password, sizeof(ci->password));
GetDlgItemText(hdlg, PORT_EDIT, ci->port, sizeof(ci->port));
sprintf(ci->readonly, "%d", IsDlgButtonChecked(hdlg, READONLY_EDIT));
if (IsDlgButtonChecked(hdlg, PG62_EDIT))
strcpy(ci->protocol, PG62);
else
ci->protocol[0] = '\0';
/* The driver connect dialog box allows manipulating this global variable */
globals.commlog = IsDlgButtonChecked(hdlg, COMMLOG_EDIT);
updateGlobals();
case IDCANCEL: case IDCANCEL:
EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
return TRUE; return TRUE;
case IDC_DRIVER:
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
hdlg, driver_optionsProc, (LPARAM) NULL);
break;
case IDC_DATASOURCE:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
hdlg, ds_optionsProc, (LPARAM) ci);
break;
} }
} }
...@@ -286,42 +283,12 @@ char *strtok_arg; ...@@ -286,42 +283,12 @@ char *strtok_arg;
if( !attribute || !value) if( !attribute || !value)
continue; continue;
/*********************************************************/ // Copy the appropriate value to the conninfo
/* PARSE ATTRIBUTES */ copyAttributes(ci, attribute, value);
/*********************************************************/
if(stricmp(attribute, "DSN") == 0)
strcpy(ci->dsn, value);
else if(stricmp(attribute, "driver") == 0)
strcpy(ci->driver, value);
else if(stricmp(attribute, "uid") == 0)
strcpy(ci->username, value);
else if(stricmp(attribute, "pwd") == 0)
strcpy(ci->password, value);
else if ((stricmp(attribute, "server") == 0) ||
(stricmp(attribute, "servername") == 0))
strcpy(ci->server, value);
else if(stricmp(attribute, "port") == 0)
strcpy(ci->port, value);
else if(stricmp(attribute, "database") == 0)
strcpy(ci->database, value);
else if (stricmp(attribute, "readonly") == 0)
strcpy(ci->readonly, value);
else if (stricmp(attribute, "protocol") == 0)
strcpy(ci->protocol, value);
else if (stricmp(attribute, "connsettings") == 0)
strcpy(ci->conn_settings, value);
} }
free(our_connect_string); free(our_connect_string);
} }
/* Module: environ.c /* Module: environ.c
* *
* Description: This module contains routines related to * Description: This module contains routines related to
* the environment, such as storing connection handles, * the environment, such as storing connection handles,
* and returning errors. * and returning errors.
* *
* Classes: EnvironmentClass (Functions prefix: "EN_") * Classes: EnvironmentClass (Functions prefix: "EN_")
* *
* API functions: SQLAllocEnv, SQLFreeEnv, SQLError * API functions: SQLAllocEnv, SQLFreeEnv, SQLError
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include "environ.h" #include "environ.h"
#include "connection.h" #include "connection.h"
...@@ -113,6 +113,10 @@ int status; ...@@ -113,6 +113,10 @@ int status;
strcpy(szSqlState, "08S01"); strcpy(szSqlState, "08S01");
// communication link failure // communication link failure
break; break;
case STMT_CREATE_TABLE_ERROR:
strcpy(szSqlState, "S0001");
// table already exists
break;
case STMT_STATUS_ERROR: case STMT_STATUS_ERROR:
case STMT_SEQUENCE_ERROR: case STMT_SEQUENCE_ERROR:
strcpy(szSqlState, "S1010"); strcpy(szSqlState, "S1010");
...@@ -158,6 +162,12 @@ int status; ...@@ -158,6 +162,12 @@ int status;
break; break;
case STMT_OPTION_VALUE_CHANGED: case STMT_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02"); strcpy(szSqlState, "01S02");
break;
case STMT_INVALID_CURSOR_NAME:
strcpy(szSqlState, "34000");
break;
case STMT_NO_CURSOR_NAME:
strcpy(szSqlState, "S1015");
break; break;
default: default:
strcpy(szSqlState, "S1000"); strcpy(szSqlState, "S1000");
...@@ -213,10 +223,10 @@ int status; ...@@ -213,10 +223,10 @@ int status;
case CONN_OPENDB_ERROR: case CONN_OPENDB_ERROR:
strcpy(szSqlState, "08001"); strcpy(szSqlState, "08001");
// unable to connect to data source // unable to connect to data source
break; break;
case CONN_INVALID_AUTHENTICATION: case CONN_INVALID_AUTHENTICATION:
case CONN_AUTH_TYPE_UNSUPPORTED: case CONN_AUTH_TYPE_UNSUPPORTED:
strcpy(szSqlState, "28000"); strcpy(szSqlState, "28000");
break; break;
case CONN_STMT_ALLOC_ERROR: case CONN_STMT_ALLOC_ERROR:
strcpy(szSqlState, "S1001"); strcpy(szSqlState, "S1001");
...@@ -339,7 +349,7 @@ EnvironmentClass *rv; ...@@ -339,7 +349,7 @@ EnvironmentClass *rv;
rv->errormsg = 0; rv->errormsg = 0;
rv->errornumber = 0; rv->errornumber = 0;
} }
return rv; return rv;
} }
...@@ -356,7 +366,7 @@ char rv = 1; ...@@ -356,7 +366,7 @@ char rv = 1;
// the source--they should not be freed // the source--they should not be freed
/* Free any connections belonging to this environment */ /* Free any connections belonging to this environment */
for (lf = 0; lf < MAX_CONNECTIONS; lf++) { for (lf = 0; lf < MAX_CONNECTIONS; lf++) {
if (conns[lf] && conns[lf]->henv == self) if (conns[lf] && conns[lf]->henv == self)
rv = rv && CC_Destructor(conns[lf]); rv = rv && CC_Destructor(conns[lf]);
} }
...@@ -383,16 +393,16 @@ char ...@@ -383,16 +393,16 @@ char
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn) EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
{ {
int i; int i;
mylog("EN_add_connection: self = %u, conn = %u\n", self, conn); mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
for (i = 0; i < MAX_CONNECTIONS; i++) { for (i = 0; i < MAX_CONNECTIONS; i++) {
if ( ! conns[i]) { if ( ! conns[i]) {
conn->henv = self; conn->henv = self;
conns[i] = conn; conns[i] = conn;
mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n", mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n",
i, conn->henv, conns[i]->henv); i, conn->henv, conns[i]->henv);
return TRUE; return TRUE;
} }
......
/* File: environ.h /* File: environ.h
* *
* Description: See "environ.c" * Description: See "environ.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __ENVIRON_H__ #ifndef __ENVIRON_H__
#define __ENVIRON_H__ #define __ENVIRON_H__
...@@ -13,15 +13,16 @@ ...@@ -13,15 +13,16 @@
#include "psqlodbc.h" #include "psqlodbc.h"
#include <windows.h> #include <windows.h>
#include <sql.h> #include <sql.h>
#include <sqlext.h>
#define ENV_ALLOC_ERROR 1 #define ENV_ALLOC_ERROR 1
/********** Environment Handle *************/ /********** Environment Handle *************/
struct EnvironmentClass_ { struct EnvironmentClass_ {
char *errormsg; char *errormsg;
int errornumber; int errornumber;
}; };
/* Environment prototypes */ /* Environment prototypes */
EnvironmentClass *EN_Constructor(void); EnvironmentClass *EN_Constructor(void);
char EN_Destructor(EnvironmentClass *self); char EN_Destructor(EnvironmentClass *self);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* Module: misc.c /* Module: misc.c
* *
* Description: This module contains miscellaneous routines * Description: This module contains miscellaneous routines
* such as for debugging/logging and string functions. * such as for debugging/logging and string functions.
* *
* Classes: n/a * Classes: n/a
* *
* API functions: none * API functions: none
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <varargs.h>
#include <sql.h>
#include "psqlodbc.h" #include "psqlodbc.h"
extern GLOBAL_VALUES globals; extern GLOBAL_VALUES globals;
#ifdef MY_LOG #ifdef MY_LOG
#include <varargs.h>
void void
mylog(va_alist) mylog(va_alist)
...@@ -52,7 +51,6 @@ static FILE *LOGFP = 0; ...@@ -52,7 +51,6 @@ static FILE *LOGFP = 0;
#ifdef Q_LOG #ifdef Q_LOG
#include <varargs.h>
void qlog(va_alist) void qlog(va_alist)
va_dcl va_dcl
...@@ -78,10 +76,17 @@ static FILE *LOGFP = 0; ...@@ -78,10 +76,17 @@ static FILE *LOGFP = 0;
} }
#endif #endif
/* Undefine these because windows.h will redefine and cause a warning */
#undef va_start
#undef va_end
#include <windows.h>
#include <sql.h>
/* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */ /* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */
int int
my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len) my_strcpy(char *dst, int dst_len, char *src, int src_len)
{ {
if (dst_len <= 0) if (dst_len <= 0)
return STRCPY_FAIL; return STRCPY_FAIL;
...@@ -90,31 +95,23 @@ my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len) ...@@ -90,31 +95,23 @@ my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len)
dst[0] = '\0'; dst[0] = '\0';
return STRCPY_NULL; return STRCPY_NULL;
} }
else if (src_len == SQL_NTS)
src_len = strlen(src);
else if (src_len == SQL_NTS) { if (src_len <= 0)
if (src_len < dst_len)
strcpy(dst, src);
else {
memcpy(dst, src, dst_len-1);
dst[dst_len-1] = '\0'; /* truncated */
return STRCPY_TRUNCATED;
}
}
else if (src_len <= 0)
return STRCPY_FAIL; return STRCPY_FAIL;
else { else {
if (src_len < dst_len) { if (src_len < dst_len) {
memcpy(dst, src, src_len); memcpy(dst, src, src_len);
dst[src_len] = '\0'; dst[src_len] = '\0';
} }
else { else {
memcpy(dst, src, dst_len-1); memcpy(dst, src, dst_len-1);
dst[dst_len-1] = '\0'; /* truncated */ dst[dst_len-1] = '\0'; /* truncated */
return STRCPY_TRUNCATED; return STRCPY_TRUNCATED;
} }
} }
return strlen(dst); return strlen(dst);
} }
...@@ -123,9 +120,9 @@ my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len) ...@@ -123,9 +120,9 @@ my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len)
// the destination string if src has len characters or more. // the destination string if src has len characters or more.
// instead, I want it to copy up to len-1 characters and always // instead, I want it to copy up to len-1 characters and always
// terminate the destination string. // terminate the destination string.
char *strncpy_null(char *dst, const char *src, size_t len) char *strncpy_null(char *dst, const char *src, int len)
{ {
unsigned int i; int i;
if (NULL != dst) { if (NULL != dst) {
...@@ -138,7 +135,7 @@ unsigned int i; ...@@ -138,7 +135,7 @@ unsigned int i;
else if (len == SQL_NTS) else if (len == SQL_NTS)
len = strlen(src) + 1; len = strlen(src) + 1;
for(i = 0; src[i] && i < len - 1; i++) { for(i = 0; src[i] && i < len - 1; i++) {
dst[i] = src[i]; dst[i] = src[i];
} }
......
/* File: misc.h /* File: misc.h
* *
* Description: See "misc.c" * Description: See "misc.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __MISC_H__ #ifndef __MISC_H__
#define __MISC_H__ #define __MISC_H__
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* Uncomment Q_LOG to compile in the qlog() statements (Communications log, i.e. CommLog). /* Uncomment Q_LOG to compile in the qlog() statements (Communications log, i.e. CommLog).
This logfile contains serious log statements that are intended for an This logfile contains serious log statements that are intended for an
end user to be able to read and understand. It is controlled by the end user to be able to read and understand. It is controlled by the
'CommLog' flag in the ODBCINST.INI portion of the registry (see above), 'CommLog' flag in the ODBCINST.INI portion of the registry (see above),
which is manipulated on the setup/connection dialog boxes. which is manipulated on the setup/connection dialog boxes.
*/ */
#define Q_LOG #define Q_LOG
...@@ -42,7 +42,7 @@ void qlog(); /* prototype */ ...@@ -42,7 +42,7 @@ void qlog(); /* prototype */
#endif #endif
void remove_newlines(char *string); void remove_newlines(char *string);
char *strncpy_null(char *dst, const char *src, size_t len); char *strncpy_null(char *dst, const char *src, int len);
char *trim(char *string); char *trim(char *string);
char *make_string(char *s, int len, char *buf); char *make_string(char *s, int len, char *buf);
char *my_strcat(char *buf, char *fmt, char *s, int len); char *my_strcat(char *buf, char *fmt, char *s, int len);
...@@ -53,6 +53,6 @@ char *my_strcat(char *buf, char *fmt, char *s, int len); ...@@ -53,6 +53,6 @@ char *my_strcat(char *buf, char *fmt, char *s, int len);
#define STRCPY_TRUNCATED -1 #define STRCPY_TRUNCATED -1
#define STRCPY_NULL -2 #define STRCPY_NULL -2
int my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len); int my_strcpy(char *dst, int dst_len, char *src, int src_len);
#endif #endif
/******************************************************************** /********************************************************************
PSQLODBC.DLL - A library to talk to the PostgreSQL DBMS using ODBC. PSQLODBC.DLL - A library to talk to the PostgreSQL DBMS using ODBC.
Copyright (C) 1998; Insight Distribution Systems Copyright (C) 1998; Insight Distribution Systems
The code contained in this library is based on code written by The code contained in this library is based on code written by
Christian Czezatke and Dan McGuirk, (C) 1996. Christian Czezatke and Dan McGuirk, (C) 1996.
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library (see "license.txt"); if not, write to License along with this library (see "license.txt"); if not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
02139, USA. 02139, USA.
How to contact the author: How to contact the author:
email: byronn@insightdist.com (Byron Nikolaidis) email: byronn@insightdist.com (Byron Nikolaidis)
***********************************************************************/ ***********************************************************************/
/* Module: options.c /* Module: options.c
* *
* Description: This module contains routines for getting/setting * Description: This module contains routines for getting/setting
* connection and statement options. * connection and statement options.
* *
* Classes: n/a * Classes: n/a
* *
* API functions: SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption, * API functions: SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption,
* SQLGetStmtOption * SQLGetStmtOption
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#include "psqlodbc.h" #include "psqlodbc.h"
#include <windows.h> #include <windows.h>
#include <sql.h> #include <sql.h>
#include <sqlext.h>
#include "environ.h" #include "environ.h"
#include "connection.h" #include "connection.h"
#include "statement.h" #include "statement.h"
extern GLOBAL_VALUES globals;
/* Implements only SQL_AUTOCOMMIT */ /* Implements only SQL_AUTOCOMMIT */
RETCODE SQL_API SQLSetConnectOption( RETCODE SQL_API SQLSetConnectOption(
HDBC hdbc, HDBC hdbc,
...@@ -81,92 +86,135 @@ ConnectionClass *conn = (ConnectionClass *) hdbc; ...@@ -81,92 +86,135 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
// - - - - - - - - - // - - - - - - - - -
/* This function just can tell you whether you are in Autcommit mode or not */
RETCODE SQL_API SQLGetConnectOption(
HDBC hdbc,
UWORD fOption,
PTR pvParam)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
if (! conn)
return SQL_INVALID_HANDLE;
switch (fOption) {
case SQL_AUTOCOMMIT:
*((UDWORD *)pvParam) = (UDWORD)( CC_is_in_autocommit(conn) ?
SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
break;
/* don't use qualifiers */
case SQL_CURRENT_QUALIFIER:
if(pvParam)
strcpy(pvParam, "");
break;
default:
conn->errormsg = "This option is currently unsupported by the driver";
conn->errornumber = CONN_UNSUPPORTED_OPTION;
return SQL_ERROR;
break;
}
return SQL_SUCCESS;
}
// - - - - - - - - -
RETCODE SQL_API SQLSetStmtOption( RETCODE SQL_API SQLSetStmtOption(
HSTMT hstmt, HSTMT hstmt,
UWORD fOption, UWORD fOption,
UDWORD vParam) UDWORD vParam)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
char changed = FALSE;
// thought we could fake Access out by just returning SQL_SUCCESS // thought we could fake Access out by just returning SQL_SUCCESS
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value // and expects the driver to reduce it to the real value
if( ! stmt) { if( ! stmt)
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
}
switch(fOption) { switch(fOption) {
case SQL_QUERY_TIMEOUT: case SQL_QUERY_TIMEOUT:
mylog("SetStmtOption: vParam = %d\n", vParam); mylog("SetStmtOption: vParam = %d\n", vParam);
/* // "0" returned in SQLGetStmtOption
stmt->errornumber = STMT_OPTION_VALUE_CHANGED; break;
stmt->errormsg = "Query Timeout: value changed to 0";
return SQL_SUCCESS_WITH_INFO; case SQL_MAX_LENGTH:
*/ // "4096" returned in SQLGetStmtOption
return SQL_SUCCESS; break;
break;
case SQL_MAX_LENGTH:
/* CC: Some apps consider returning SQL_SUCCESS_WITH_INFO to be an error */
/* so if we're going to return SQL_SUCCESS, we better not set an */
/* error message. (otherwise, if a subsequent function call returns */
/* SQL_ERROR without setting a message, things can get confused.) */
/*
stmt->errormsg = "Requested value changed.";
stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
*/
return SQL_SUCCESS;
break;
case SQL_MAX_ROWS: case SQL_MAX_ROWS:
mylog("SetStmtOption(): SQL_MAX_ROWS = %d, returning success\n", vParam); mylog("SetStmtOption(): SQL_MAX_ROWS = %d, returning success\n", vParam);
stmt->maxRows = vParam; stmt->maxRows = vParam;
return SQL_SUCCESS; return SQL_SUCCESS;
break; break;
default:
return SQL_ERROR;
}
return SQL_SUCCESS; case SQL_ROWSET_SIZE:
} mylog("SetStmtOption(): SQL_ROWSET_SIZE = %d\n", vParam);
// - - - - - - - - - stmt->rowset_size = 1; // only support 1 row at a time
if (vParam != 1)
changed = TRUE;
/* This function just can tell you whether you are in Autcommit mode or not */ break;
RETCODE SQL_API SQLGetConnectOption(
HDBC hdbc, case SQL_CONCURRENCY:
UWORD fOption, // positioned update isn't supported so cursor concurrency is read-only
PTR pvParam) mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);
{
ConnectionClass *conn = (ConnectionClass *) hdbc; stmt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (vParam != SQL_CONCUR_READ_ONLY)
changed = TRUE;
break;
case SQL_CURSOR_TYPE:
// if declare/fetch, then type can only be forward.
// otherwise, it can only be forward or static.
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d\n", vParam);
if (globals.use_declarefetch) {
stmt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
if (vParam != SQL_CURSOR_FORWARD_ONLY)
changed = TRUE;
}
else {
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
stmt->cursor_type = vParam; // valid type
else {
stmt->cursor_type = SQL_CURSOR_STATIC;
changed = TRUE;
}
}
break;
case SQL_SIMULATE_CURSOR:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported";
return SQL_ERROR;
if (! conn)
return SQL_INVALID_HANDLE;
switch (fOption) {
case SQL_AUTOCOMMIT:
/* CC 28.05.96: Do not set fOption, but pvParam */
*((UDWORD *)pvParam) = (UDWORD)( CC_is_in_autocommit(conn) ?
SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
break;
/* we don't use qualifiers */
case SQL_CURRENT_QUALIFIER:
if(pvParam) {
strcpy(pvParam, "");
}
break;
default: default:
conn->errormsg = "This option is currently unsupported by the driver"; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
conn->errornumber = CONN_UNSUPPORTED_OPTION; stmt->errormsg = "Driver does not support this statement option";
return SQL_ERROR; return SQL_ERROR;
break; }
}
return SQL_SUCCESS; if (changed) {
stmt->errormsg = "Requested value changed.";
stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
return SQL_SUCCESS_WITH_INFO;
}
else
return SQL_SUCCESS;
} }
// - - - - - - - - - // - - - - - - - - -
RETCODE SQL_API SQLGetStmtOption( RETCODE SQL_API SQLGetStmtOption(
...@@ -180,31 +228,54 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -180,31 +228,54 @@ StatementClass *stmt = (StatementClass *) hstmt;
// all the time, but it tries to set a huge value for SQL_MAX_LENGTH // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
// and expects the driver to reduce it to the real value // and expects the driver to reduce it to the real value
if( ! stmt) { if( ! stmt)
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
}
switch(fOption) {
case SQL_QUERY_TIMEOUT:
// how long we wait on a query before returning to the
// application (0 == forever)
*((SDWORD *)pvParam) = 0;
break;
case SQL_MAX_LENGTH:
// what is the maximum length that will be returned in
// a single column
*((SDWORD *)pvParam) = 4096;
break;
switch(fOption) {
case SQL_QUERY_TIMEOUT:
// how long we wait on a query before returning to the
// application (0 == forever)
*((SDWORD *)pvParam) = 0;
break;
case SQL_MAX_LENGTH:
// what is the maximum length that will be returned in
// a single column
*((SDWORD *)pvParam) = 4096;
break;
case SQL_MAX_ROWS: case SQL_MAX_ROWS:
*((SDWORD *)pvParam) = stmt->maxRows; *((SDWORD *)pvParam) = stmt->maxRows;
mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->maxRows); mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->maxRows);
break;
case SQL_ROWSET_SIZE:
mylog("GetStmtOption(): SQL_ROWSET_SIZE\n");
*((SDWORD *)pvParam) = stmt->rowset_size;
break;
case SQL_CONCURRENCY:
mylog("GetStmtOption(): SQL_CONCURRENCY\n");
*((SDWORD *)pvParam) = stmt->scroll_concurrency;
break; break;
default:
return SQL_ERROR;
}
return SQL_SUCCESS; case SQL_CURSOR_TYPE:
mylog("GetStmtOption(): SQL_CURSOR_TYPE\n");
*((SDWORD *)pvParam) = stmt->cursor_type;
break;
case SQL_SIMULATE_CURSOR:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported";
return SQL_ERROR;
default:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support this statement option";
return SQL_ERROR;
}
return SQL_SUCCESS;
} }
// - - - - - - - - - // - - - - - - - - -
This diff is collapsed.
/* File: pgtypes.h /* File: pgtypes.h
* *
* Description: See "pgtypes.c" * Description: See "pgtypes.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __PGTYPES_H__ #ifndef __PGTYPES_H__
#define __PGTYPES_H__ #define __PGTYPES_H__
#include "psqlodbc.h"
/* the type numbers are defined by the OID's of the types' rows */ /* the type numbers are defined by the OID's of the types' rows */
/* in table pg_type */ /* in table pg_type */
#define PG_UNKNOWN -666 /* returned only from pgtype_to_sqltype() */
// #define PG_TYPE_LO ???? /* waiting for permanent type */
#define PG_TYPE_BOOL 16 #define PG_TYPE_BOOL 16
#define PG_TYPE_BYTEA 17 #define PG_TYPE_BYTEA 17
...@@ -58,22 +61,30 @@ ...@@ -58,22 +61,30 @@
extern Int4 pgtypes_defined[]; extern Int4 pgtypes_defined[];
Int2 pgtype_to_sqltype(Int4 type); /* Defines for pgtype_precision */
Int2 pgtype_to_ctype(Int4 type); #define PG_STATIC -1
char *pgtype_to_name(Int4 type);
Int4 pgtype_precision(Int4 type);
Int4 pgtype_length(Int4 type); Int2 pgtype_to_sqltype(StatementClass *stmt, Int4 type);
Int2 pgtype_scale(Int4 type); Int2 pgtype_to_ctype(StatementClass *stmt, Int4 type);
Int2 pgtype_radix(Int4 type); char *pgtype_to_name(StatementClass *stmt, Int4 type);
Int2 pgtype_nullable(Int4 type);
Int2 pgtype_auto_increment(Int4 type); /* These functions can use static numbers or result sets(col parameter) */
Int2 pgtype_case_sensitive(Int4 type); Int4 pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_money(Int4 type); Int4 pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_searchable(Int4 type); Int4 pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_unsigned(Int4 type);
char *pgtype_literal_prefix(Int4 type); Int2 pgtype_scale(StatementClass *stmt, Int4 type);
char *pgtype_literal_suffix(Int4 type); Int2 pgtype_radix(StatementClass *stmt, Int4 type);
char *pgtype_create_params(Int4 type); Int2 pgtype_nullable(StatementClass *stmt, Int4 type);
Int2 pgtype_auto_increment(StatementClass *stmt, Int4 type);
Int2 pgtype_case_sensitive(StatementClass *stmt, Int4 type);
Int2 pgtype_money(StatementClass *stmt, Int4 type);
Int2 pgtype_searchable(StatementClass *stmt, Int4 type);
Int2 pgtype_unsigned(StatementClass *stmt, Int4 type);
char *pgtype_literal_prefix(StatementClass *stmt, Int4 type);
char *pgtype_literal_suffix(StatementClass *stmt, Int4 type);
char *pgtype_create_params(StatementClass *stmt, Int4 type);
Int2 sqltype_to_default_ctype(Int2 sqltype); Int2 sqltype_to_default_ctype(Int2 sqltype);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* File: qresult.h /* File: qresult.h
* *
* Description: See "qresult.c" * Description: See "qresult.c"
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
*/ */
#ifndef __QRESULT_H__ #ifndef __QRESULT_H__
#define __QRESULT_H__ #define __QRESULT_H__
...@@ -43,7 +43,7 @@ struct QResultClass_ { ...@@ -43,7 +43,7 @@ struct QResultClass_ {
// Stuff for declare/fetch tuples // Stuff for declare/fetch tuples
int fetch_count; // logical rows read so far int fetch_count; // logical rows read so far
int fcount; // actual rows read in the fetch int fcount; // actual rows read in the fetch
int num_fields; // number of fields in the result int num_fields; // number of fields in the result
QueryResultCode status; QueryResultCode status;
...@@ -63,19 +63,22 @@ struct QResultClass_ { ...@@ -63,19 +63,22 @@ struct QResultClass_ {
/* These functions are for retrieving data from the qresult */ /* These functions are for retrieving data from the qresult */
#define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno)) #define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno))
#define QR_get_value_backend(self, fieldno) (self->tupleField[fieldno].value) #define QR_get_value_backend(self, fieldno) (self->tupleField[fieldno].value)
#define QR_get_value_backend_row(self, tupleno, fieldno) \
((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value)
/* These functions are used by both manual and backend results */ /* These functions are used by both manual and backend results */
#define QR_NumResultCols(self) (CI_get_num_fields(self->fields)) #define QR_NumResultCols(self) (CI_get_num_fields(self->fields))
#define QR_get_fieldname(self, fieldno_) (CI_get_fieldname(self->fields, fieldno_)) #define QR_get_fieldname(self, fieldno_) (CI_get_fieldname(self->fields, fieldno_))
#define QR_get_fieldsize(self, fieldno_) (CI_get_fieldsize(self->fields, fieldno_)) #define QR_get_fieldsize(self, fieldno_) (CI_get_fieldsize(self->fields, fieldno_))
#define QR_get_field_type(self, fieldno_) (CI_get_oid(self->fields, fieldno_)) #define QR_get_display_size(self, fieldno_) (CI_get_display_size(self->fields, fieldno_))
#define QR_get_field_type(self, fieldno_) (CI_get_oid(self->fields, fieldno_))
/* These functions are used only for manual result sets */ /* These functions are used only for manual result sets */
#define QR_get_num_tuples(self) (self->manual_tuples ? TL_get_num_tuples(self->manual_tuples) : 0) #define QR_get_num_tuples(self) (self->manual_tuples ? TL_get_num_tuples(self->manual_tuples) : self->fcount)
#define QR_add_tuple(self, new_tuple) (TL_add_tuple(self->manual_tuples, new_tuple)) #define QR_add_tuple(self, new_tuple) (TL_add_tuple(self->manual_tuples, new_tuple))
#define QR_set_field_info(self, field_num, name, adtid, adtsize) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize)) #define QR_set_field_info(self, field_num, name, adtid, adtsize) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize))
/* status macros */ /* status macros */
#define QR_command_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR)) #define QR_command_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR))
...@@ -98,7 +101,7 @@ int QR_close(QResultClass *self); ...@@ -98,7 +101,7 @@ int QR_close(QResultClass *self);
char QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor); char QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor);
void QR_free_memory(QResultClass *self); void QR_free_memory(QResultClass *self);
void QR_set_command(QResultClass *self, char *msg); void QR_set_command(QResultClass *self, char *msg);
void QR_set_notice(QResultClass *self, char *msg); void QR_set_notice(QResultClass *self, char *msg);
void QR_set_num_fields(QResultClass *self, int new_num_fields); /* manual result only */ void QR_set_num_fields(QResultClass *self, int new_num_fields); /* manual result only */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment