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

Update odbc driver to current version V.0244

parent 85f91d0e
...@@ -79,6 +79,7 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -79,6 +79,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
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].lobj_oid = 0;
stmt->parameters[i].EXEC_used = NULL; stmt->parameters[i].EXEC_used = NULL;
stmt->parameters[i].EXEC_buffer = NULL; stmt->parameters[i].EXEC_buffer = NULL;
} }
...@@ -114,6 +115,8 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -114,6 +115,8 @@ StatementClass *stmt = (StatementClass *) hstmt;
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; if (pcpar) {
stmt->errormsg = "SQLNumParams called with no statement ready."; *pcpar = stmt->parameters_allocated;
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; 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 */
......
...@@ -34,8 +34,9 @@ struct ParameterInfoClass_ { ...@@ -34,8 +34,9 @@ struct ParameterInfoClass_ {
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 *EXEC_buffer; /* the data or the FD of the large object */
char data_at_exec; char data_at_exec;
}; };
......
...@@ -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;
...@@ -98,6 +99,7 @@ int num_fields = self->num_fields; ...@@ -98,6 +99,7 @@ int num_fields = self->num_fields;
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 *
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) self->display_size[field_num] = 0;
return 0;
if ((which >= 0) && (which < self->num_fields))
rv = self->adtsize[which];
return rv;
} }
...@@ -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.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#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 {
...@@ -119,6 +120,7 @@ typedef struct _StartupPacket6_2 ...@@ -119,6 +120,7 @@ typedef struct _StartupPacket6_2
*/ */
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];
...@@ -128,6 +130,10 @@ typedef struct { ...@@ -128,6 +130,10 @@ typedef struct {
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;
...@@ -135,6 +141,7 @@ typedef struct { ...@@ -135,6 +141,7 @@ typedef struct {
#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? */
}; };
...@@ -167,10 +175,9 @@ struct ConnectionClass_ { ...@@ -167,10 +175,9 @@ struct ConnectionClass_ {
/* 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);
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); char CC_send_settings(ConnectionClass *self);
void CC_lookup_lo(ConnectionClass *conn);
#endif #endif
This diff is collapsed.
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#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
...@@ -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;
...@@ -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;
/* Change the caption for the setup dialog */
SetWindowText(hdlg, "PostgreSQL Connection");
SetWindowText(GetDlgItem(hdlg, IDC_DATASOURCE), "Connection");
SetDlgItemText(hdlg, SERVER_EDIT, ci->server); /* Hide the DSN and description fields */
SetDlgItemText(hdlg, DATABASE_EDIT, ci->database); ShowWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), SW_HIDE);
SetDlgItemText(hdlg, USERNAME_EDIT, ci->username); ShowWindow(GetDlgItem(hdlg, IDC_DSNAME), SW_HIDE);
SetDlgItemText(hdlg, PASSWORD_EDIT, ci->password); ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
SetDlgItemText(hdlg, PORT_EDIT, ci->port); ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
CheckDlgButton(hdlg, READONLY_EDIT, atoi(ci->readonly));
CheckDlgButton(hdlg, PG62_EDIT, PROTOCOL_62(ci)); SetWindowLong(hdlg, DWL_USER, lParam);// Save the ConnInfo for the "OK"
/* The driver connect dialog box allows manipulating this global variable */ SetDlgStuff(hdlg, ci);
CheckDlgButton(hdlg, COMMLOG_EDIT, globals.commlog);
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));
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)); GetDlgStuff(hdlg, ci);
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);
} }
...@@ -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");
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#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
......
This diff is collapsed.
This diff is collapsed.
...@@ -13,16 +13,15 @@ ...@@ -13,16 +13,15 @@
*/ */
#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,18 +95,10 @@ my_strcpy(char *dst, size_t dst_len, char *src, size_t src_len) ...@@ -90,18 +95,10 @@ 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 {
...@@ -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) {
......
...@@ -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
...@@ -16,10 +16,15 @@ ...@@ -16,10 +16,15 @@
#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;
stmt->errormsg = "Query Timeout: value changed to 0";
return SQL_SUCCESS_WITH_INFO;
*/
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; case SQL_MAX_LENGTH:
// "4096" returned in SQLGetStmtOption
break; 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,
UWORD fOption,
PTR pvParam)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
if (! conn) case SQL_CONCURRENCY:
return SQL_INVALID_HANDLE; // positioned update isn't supported so cursor concurrency is read-only
mylog("SetStmtOption(): SQL_CONCURRENCY = %d\n", vParam);
stmt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
if (vParam != SQL_CONCUR_READ_ONLY)
changed = TRUE;
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; break;
/* we don't use qualifiers */
case SQL_CURRENT_QUALIFIER: case SQL_CURSOR_TYPE:
if(pvParam) { // if declare/fetch, then type can only be forward.
strcpy(pvParam, ""); // 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; break;
default:
conn->errormsg = "This option is currently unsupported by the driver"; case SQL_SIMULATE_CURSOR:
conn->errornumber = CONN_UNSUPPORTED_OPTION; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported";
return SQL_ERROR; return SQL_ERROR;
break;
default:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support this statement option";
return SQL_ERROR;
} }
if (changed) {
stmt->errormsg = "Requested value changed.";
stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
return SQL_SUCCESS_WITH_INFO;
}
else
return SQL_SUCCESS; return SQL_SUCCESS;
} }
// - - - - - - - - - // - - - - - - - - -
RETCODE SQL_API SQLGetStmtOption( RETCODE SQL_API SQLGetStmtOption(
...@@ -180,9 +228,8 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -180,9 +228,8 @@ 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) { switch(fOption) {
case SQL_QUERY_TIMEOUT: case SQL_QUERY_TIMEOUT:
...@@ -190,17 +237,41 @@ StatementClass *stmt = (StatementClass *) hstmt; ...@@ -190,17 +237,41 @@ StatementClass *stmt = (StatementClass *) hstmt;
// application (0 == forever) // application (0 == forever)
*((SDWORD *)pvParam) = 0; *((SDWORD *)pvParam) = 0;
break; break;
case SQL_MAX_LENGTH: case SQL_MAX_LENGTH:
// what is the maximum length that will be returned in // what is the maximum length that will be returned in
// a single column // a single column
*((SDWORD *)pvParam) = 4096; *((SDWORD *)pvParam) = 4096;
break; 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;
case SQL_CURSOR_TYPE:
mylog("GetStmtOption(): SQL_CURSOR_TYPE\n");
*((SDWORD *)pvParam) = stmt->cursor_type;
break; break;
case SQL_SIMULATE_CURSOR:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Simulated positioned update/delete not supported";
return SQL_ERROR;
default: default:
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Driver does not support this statement option";
return SQL_ERROR; return SQL_ERROR;
} }
......
This diff is collapsed.
...@@ -10,10 +10,13 @@ ...@@ -10,10 +10,13 @@
#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);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
*/ */
#include "psqlodbc.h" #include "psqlodbc.h"
#include "dlg_specific.h"
#include <winsock.h> #include <winsock.h>
#include <windows.h> #include <windows.h>
#include <sql.h> #include <sql.h>
...@@ -23,67 +24,6 @@ HINSTANCE NEAR s_hModule; /* Saved module handle. */ ...@@ -23,67 +24,6 @@ HINSTANCE NEAR s_hModule; /* Saved module handle. */
GLOBAL_VALUES globals; GLOBAL_VALUES globals;
/* This function reads the ODBCINST.INI portion of
the registry and gets any driver defaults.
*/
void getGlobalDefaults(void)
{
char temp[128];
// Fetch Count is stored in driver section
SQLGetPrivateProfileString(DBMS_NAME, INI_FETCH, "",
temp, sizeof(temp), ODBCINST_INI);
if ( temp[0] )
globals.fetch_max = atoi(temp);
else
globals.fetch_max = FETCH_MAX;
// Socket Buffersize is stored in driver section
SQLGetPrivateProfileString(DBMS_NAME, INI_SOCKET, "",
temp, sizeof(temp), ODBCINST_INI);
if ( temp[0] )
globals.socket_buffersize = atoi(temp);
else
globals.socket_buffersize = SOCK_BUFFER_SIZE;
// Debug is stored in the driver section
SQLGetPrivateProfileString(DBMS_NAME, INI_DEBUG, "0",
temp, sizeof(temp), ODBCINST_INI);
globals.debug = atoi(temp);
// CommLog is stored in the driver section
SQLGetPrivateProfileString(DBMS_NAME, INI_COMMLOG, "0",
temp, sizeof(temp), ODBCINST_INI);
globals.commlog = atoi(temp);
// Optimizer is stored in the driver section only (OFF, ON, or ON=x)
SQLGetPrivateProfileString(DBMS_NAME, INI_OPTIMIZER, "",
globals.optimizer, sizeof(globals.optimizer), ODBCINST_INI);
// ConnSettings is stored in the driver section and per datasource for override
SQLGetPrivateProfileString(DBMS_NAME, INI_CONNSETTINGS, "",
globals.conn_settings, sizeof(globals.conn_settings), ODBCINST_INI);
}
/* This function writes any global parameters (that can be manipulated)
to the ODBCINST.INI portion of the registry
*/
void updateGlobals(void)
{
char tmp[128];
sprintf(tmp, "%d", globals.commlog);
SQLWritePrivateProfileString(DBMS_NAME,
INI_COMMLOG, tmp, ODBCINST_INI);
}
/* This is where the Driver Manager attaches to this Driver */ /* This is where the Driver Manager attaches to this Driver */
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{ {
......
...@@ -24,6 +24,7 @@ typedef UInt4 Oid; ...@@ -24,6 +24,7 @@ typedef UInt4 Oid;
#define MAX_CONNECT_STRING 4096 #define MAX_CONNECT_STRING 4096
#define ERROR_MSG_LENGTH 4096 #define ERROR_MSG_LENGTH 4096
#define FETCH_MAX 100 /* default number of rows to cache for declare/fetch */ #define FETCH_MAX 100 /* default number of rows to cache for declare/fetch */
#define FETCH_INCR 1000
#define SOCK_BUFFER_SIZE 4096 /* default socket buffer size */ #define SOCK_BUFFER_SIZE 4096 /* default socket buffer size */
#define MAX_CONNECTIONS 128 /* conns per environment (arbitrary) */ #define MAX_CONNECTIONS 128 /* conns per environment (arbitrary) */
#define MAX_FIELDS 512 #define MAX_FIELDS 512
...@@ -32,16 +33,11 @@ typedef UInt4 Oid; ...@@ -32,16 +33,11 @@ typedef UInt4 Oid;
/* Registry length limits */ /* Registry length limits */
#define LARGE_REGISTRY_LEN 4096 /* used for special cases */ #define LARGE_REGISTRY_LEN 4096 /* used for special cases */
#define MEDIUM_REGISTRY_LEN 128 /* normal size for user,database,etc. */ #define MEDIUM_REGISTRY_LEN 256 /* normal size for user,database,etc. */
#define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */ #define SMALL_REGISTRY_LEN 10 /* for 1/0 settings */
/* Connection Defaults */
#define DEFAULT_PORT "5432"
#define DEFAULT_READONLY "1"
/* These prefixes denote system tables */ /* These prefixes denote system tables */
#define INSIGHT_SYS_PREFIX "dd_"
#define POSTGRES_SYS_PREFIX "pg_" #define POSTGRES_SYS_PREFIX "pg_"
#define KEYS_TABLE "dd_fkey" #define KEYS_TABLE "dd_fkey"
...@@ -54,33 +50,13 @@ typedef UInt4 Oid; ...@@ -54,33 +50,13 @@ typedef UInt4 Oid;
/* Driver stuff */ /* Driver stuff */
#define DRIVERNAME "PostgreSQL ODBC" #define DRIVERNAME "PostgreSQL ODBC"
#define DBMS_NAME "PostgreSQL" #define DBMS_NAME "PostgreSQL"
#define DBMS_VERSION "06.30.0000 PostgreSQL 6.3" #define DBMS_VERSION "06.30.0244 PostgreSQL 6.3"
#define POSTGRESDRIVERVERSION "06.30.0000" #define POSTGRESDRIVERVERSION "06.30.0244"
#define DRIVER_FILE_NAME "PSQLODBC.DLL" #define DRIVER_FILE_NAME "PSQLODBC.DLL"
#define PG62 "6.2" /* "Protocol" key setting to force Postgres 6.2 */ #define PG62 "6.2" /* "Protocol" key setting to force Postgres 6.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 */
typedef struct ConnectionClass_ ConnectionClass; typedef struct ConnectionClass_ ConnectionClass;
typedef struct StatementClass_ StatementClass; typedef struct StatementClass_ StatementClass;
...@@ -94,26 +70,39 @@ typedef struct EnvironmentClass_ EnvironmentClass; ...@@ -94,26 +70,39 @@ typedef struct EnvironmentClass_ EnvironmentClass;
typedef struct TupleNode_ TupleNode; typedef struct TupleNode_ TupleNode;
typedef struct TupleField_ TupleField; typedef struct TupleField_ TupleField;
typedef struct lo_arg LO_ARG;
typedef struct GlobalValues_ typedef struct GlobalValues_
{ {
int fetch_max; int fetch_max;
int socket_buffersize; int socket_buffersize;
int debug; int unknown_sizes;
int commlog; int max_varchar_size;
char optimizer[MEDIUM_REGISTRY_LEN]; int max_longvarchar_size;
char debug;
char commlog;
char disable_optimizer;
char unique_index;
char readonly;
char use_declarefetch;
char text_as_longvarchar;
char unknowns_as_longvarchar;
char bools_as_char;
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
char conn_settings[LARGE_REGISTRY_LEN]; char conn_settings[LARGE_REGISTRY_LEN];
} GLOBAL_VALUES; } GLOBAL_VALUES;
#define PG_TYPE_LO -999 /* hack until permanent type available */
#define PG_TYPE_LO_NAME "lo"
#define OID_ATTNUM -2 /* the attnum in pg_index of the oid */
/* sizes */ /* sizes */
#define TEXT_FIELD_SIZE 4094 /* size of text fields (not including null term) */ #define TEXT_FIELD_SIZE 4094 /* size of text fields (not including null term) */
#define NAME_FIELD_SIZE 32 /* size of name fields */
#define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */ #define MAX_VARCHAR_SIZE 254 /* maximum size of a varchar (not including null term) */
/* global prototypes */
void updateGlobals(void);
#include "misc.h" #include "misc.h"
......
This diff is collapsed.
This diff is collapsed.
...@@ -65,15 +65,18 @@ struct QResultClass_ { ...@@ -65,15 +65,18 @@ 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_display_size(self, fieldno_) (CI_get_display_size(self->fields, fieldno_))
#define QR_get_field_type(self, fieldno_) (CI_get_oid(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))
......
Readme for psqlodbc.dll 4/15/98
-------------------------------------------------------------------------------
Latest binary and source updates available at http://www.insightdist.com/psqlodbc
I. Building the Driver from the source code
This section describes how to build the PostgreSQL ODBC Driver (psqlodbc.dll).
Microsoft Visual C++ version 4.0 or higher is required. There is no manually
constructed Makefile. The visual C++ environment automatically generates one
during the build process. Thus, the project binary files (".ncb", ".mdp", ".aps")
nor the makefile are really distributed as part of the source code release
(although they are probably in there anyway).
1. Create a new project workspace with the type DLL. For the name, type in the
name "psqlodbc".
2. The above step creates the directory "psqlodbc" under the
"\<Visual C++ top level directory>\projects" path to hold the source files.
(example, \msdev\projects\psqlodbc). Now, either unzip the source code release
into this directory or just copy all the files into this directory.
3. Insert all of the source files (*.c, *.h, *.rc, *.def) into the Visual project
using the "Insert files into project" command. You may have to do 2 inserts --
the first to get the 'c' and header files, and the second to get the def file.
Don't forget the .def file since it is an important part of the release.
You can even insert ".txt" files into the projects -- they will do nothing.
4. Add the "wsock32.lib" library to the end of the list of libraries for linking
using the Build settings menu.
5. Select the type of build on the toolbar (i.e., Release or Debug). This is
one of the useful features of the visual c++ environment in that you can
browse the entire project if you build the "Debug" release. For release
purposes however, select "Release" build.
6. Build the dll by selecting Build from the build menu.
7. When complete, the "psqlodbc.dll" file is under the "Release" subdirectory.
(i.e., "\msdev\projects\psqlodbc\release\psqlodbc.dll")
II. Using Large Objects for handling LongVarBinary (OLE Objects in Access)
Large objects are mapped to LONGVARBINARY in the driver to allow storing things like
OLE objects in Microsoft Access. Multiple SQLPutData and SQLGetData calls are usually
used to send and retrieve these objects. The driver creates a new large object and simply
inserts its 'identifier' into the respective table. However, since Postgres uses an 'Oid'
to identify a Large Object, it is necessary to create a new Postgres type to be able
to discriminate between an ordinary Oid and a Large Object Oid. Until this new type
becomes an official part of Postgres, it must be added into the desired database and
looked up for each connection. The type used in the driver is simply called "lo" and
here is the command used to create it:
create type lo (internallength=4,externallength=10,input=int4in,output=int4out,
default='',passedbyvalue);
Once this is done, simply use the new 'lo' type to define columns in that database. Note
that this must be done for each database you want to use large objects in with the driver.
When the driver sees an 'lo' type, it will handle it as LONGVARBINARY.
Another important note is that this new type is lacking in functionality. It will not
cleanup after itself on updates and deletes, thus leaving orphans around and using up
extra disk space. And currently, Postgres does not support the vacuuming of large
objects. Hopefully in the future, a real large object data type will be available.
But for now, it sure is fun to stick a Word document, Visio document, or avi of a dancing
baby into a database column, even if you will fill up your server's hard disk after a while!
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -77,6 +77,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname) ...@@ -77,6 +77,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
{ {
struct hostent *host; struct hostent *host;
struct sockaddr_in sadr; struct sockaddr_in sadr;
unsigned long iaddr;
if (self->socket != -1) { if (self->socket != -1) {
self->errornumber = SOCKET_ALREADY_CONNECTED; self->errornumber = SOCKET_ALREADY_CONNECTED;
...@@ -84,15 +85,24 @@ struct sockaddr_in sadr; ...@@ -84,15 +85,24 @@ struct sockaddr_in sadr;
return 0; return 0;
} }
memset((char *)&sadr, 0, sizeof(sadr));
/* If it is a valid IP address, use it.
Otherwise use hostname lookup.
*/
iaddr = inet_addr(hostname);
if (iaddr == INADDR_NONE) {
host = gethostbyname(hostname); host = gethostbyname(hostname);
if (host == NULL) { if (host == NULL) {
self->errornumber = SOCKET_HOST_NOT_FOUND; self->errornumber = SOCKET_HOST_NOT_FOUND;
self->errormsg = "Could not resolve hostname."; self->errormsg = "Could not resolve hostname.";
return 0; return 0;
} }
memset((char *)&sadr, 0, sizeof(sadr));
memcpy(&(sadr.sin_addr), host->h_addr, host->h_length); memcpy(&(sadr.sin_addr), host->h_addr, host->h_length);
}
else
memcpy(&(sadr.sin_addr), (struct in_addr *) &iaddr, sizeof(iaddr));
sadr.sin_family = AF_INET; sadr.sin_family = AF_INET;
sadr.sin_port = htons(port); sadr.sin_port = htons(port);
......
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