mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
ODBC source code cleanup patch. Should match rest of PostgreSQL code better.
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
/* 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.
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* SQLParamOptions(NI)
|
* SQLParamOptions(NI)
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -33,8 +34,8 @@
|
|||||||
#include "sqlext.h"
|
#include "sqlext.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Bind parameters on a statement handle */
|
|
||||||
|
|
||||||
|
/* Bind parameters on a statement handle */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLBindParameter(
|
SQLBindParameter(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -112,8 +113,8 @@ SQLBindParameter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ipar--; /* use zero based column numbers for the
|
/* use zero based column numbers for the below part */
|
||||||
* below part */
|
ipar--;
|
||||||
|
|
||||||
/* store the given info */
|
/* store the given info */
|
||||||
stmt->parameters[ipar].buflen = cbValueMax;
|
stmt->parameters[ipar].buflen = cbValueMax;
|
||||||
@ -158,7 +159,6 @@ SQLBindParameter(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Associate a user-supplied buffer with a database column. */
|
/* Associate a user-supplied buffer with a database column. */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
@ -197,7 +197,6 @@ SQLBindCol(
|
|||||||
/* If the bookmark column is being bound, then just save it */
|
/* If the bookmark column is being bound, then just save it */
|
||||||
if (icol == 0)
|
if (icol == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (rgbValue == NULL)
|
if (rgbValue == NULL)
|
||||||
{
|
{
|
||||||
stmt->bookmark.buffer = NULL;
|
stmt->bookmark.buffer = NULL;
|
||||||
@ -220,10 +219,12 @@ SQLBindCol(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate enough bindings if not already done */
|
/*
|
||||||
/* Most likely, execution of a statement would have setup the */
|
* Allocate enough bindings if not already done.
|
||||||
/* necessary bindings. But some apps call BindCol before any */
|
* Most likely, execution of a statement would have setup the
|
||||||
/* statement is executed. */
|
* necessary bindings. But some apps call BindCol before any
|
||||||
|
* statement is executed.
|
||||||
|
*/
|
||||||
if (icol > stmt->bindings_allocated)
|
if (icol > stmt->bindings_allocated)
|
||||||
extend_bindings(stmt, icol);
|
extend_bindings(stmt, icol);
|
||||||
|
|
||||||
@ -236,8 +237,8 @@ SQLBindCol(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
icol--; /* use zero based col numbers from here
|
/* use zero based col numbers from here out */
|
||||||
* out */
|
icol--;
|
||||||
|
|
||||||
/* Reset for SQLGetData */
|
/* Reset for SQLGetData */
|
||||||
stmt->bindings[icol].data_left = -1;
|
stmt->bindings[icol].data_left = -1;
|
||||||
@ -264,15 +265,15 @@ SQLBindCol(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Returns the description of a parameter marker. */
|
|
||||||
/* This function is listed as not being supported by SQLGetFunctions() because it is */
|
|
||||||
/* used to describe "parameter markers" (not bound parameters), in which case, */
|
|
||||||
/* the dbms should return info on the markers. Since Postgres doesn't support that, */
|
|
||||||
/* it is best to say this function is not supported and let the application assume a */
|
|
||||||
/* data type (most likely varchar). */
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the description of a parameter marker.
|
||||||
|
* This function is listed as not being supported by SQLGetFunctions() because it is
|
||||||
|
* used to describe "parameter markers" (not bound parameters), in which case,
|
||||||
|
* the dbms should return info on the markers. Since Postgres doesn't support that,
|
||||||
|
* it is best to say this function is not supported and let the application assume a
|
||||||
|
* data type (most likely varchar).
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLDescribeParam(
|
SQLDescribeParam(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -323,10 +324,8 @@ SQLDescribeParam(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Sets multiple values (arrays) for the set of parameter markers. */
|
/* Sets multiple values (arrays) for the set of parameter markers. */
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLParamOptions(
|
SQLParamOptions(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -341,15 +340,16 @@ SQLParamOptions(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* This function should really talk to the dbms to determine the number of */
|
/*
|
||||||
/* "parameter markers" (not bound parameters) in the statement. But, since */
|
* This function should really talk to the dbms to determine the number of
|
||||||
/* Postgres doesn't support that, the driver should just count the number of markers */
|
* "parameter markers" (not bound parameters) in the statement. But, since
|
||||||
/* and return that. The reason the driver just can't say this function is unsupported */
|
* Postgres doesn't support that, the driver should just count the number of markers
|
||||||
/* like it does for SQLDescribeParam is that some applications don't care and try */
|
* and return that. The reason the driver just can't say this function is unsupported
|
||||||
/* to call it anyway. */
|
* like it does for SQLDescribeParam is that some applications don't care and try
|
||||||
/* If the statement does not have parameters, it should just return 0. */
|
* to call it anyway.
|
||||||
|
* If the statement does not have parameters, it should just return 0.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLNumParams(
|
SQLNumParams(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -387,10 +387,8 @@ SQLNumParams(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
for (i = 0; i < strlen(stmt->statement); i++)
|
for (i = 0; i < strlen(stmt->statement); i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stmt->statement[i] == '?' && !in_quote)
|
if (stmt->statement[i] == '?' && !in_quote)
|
||||||
(*pcpar)++;
|
(*pcpar)++;
|
||||||
else
|
else
|
||||||
@ -399,12 +397,12 @@ SQLNumParams(
|
|||||||
in_quote = (in_quote ? FALSE : TRUE);
|
in_quote = (in_quote ? FALSE : TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
|
/*
|
||||||
* Bindings Implementation
|
* Bindings Implementation
|
||||||
*/
|
*/
|
||||||
BindInfoClass *
|
BindInfoClass *
|
||||||
@ -428,6 +426,7 @@ create_empty_bindings(int num_columns)
|
|||||||
return new_bindings;
|
return new_bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
extend_bindings(StatementClass *stmt, int num_columns)
|
extend_bindings(StatementClass *stmt, int num_columns)
|
||||||
{
|
{
|
||||||
@ -437,11 +436,12 @@ extend_bindings(StatementClass *stmt, int num_columns)
|
|||||||
|
|
||||||
mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
|
mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
|
||||||
|
|
||||||
/* if we have too few, allocate room for more, and copy the old */
|
/*
|
||||||
/* entries into the new structure */
|
* if we have too few, allocate room for more, and copy the old
|
||||||
|
* entries into the new structure
|
||||||
|
*/
|
||||||
if (stmt->bindings_allocated < num_columns)
|
if (stmt->bindings_allocated < num_columns)
|
||||||
{
|
{
|
||||||
|
|
||||||
new_bindings = create_empty_bindings(num_columns);
|
new_bindings = create_empty_bindings(num_columns);
|
||||||
if (!new_bindings)
|
if (!new_bindings)
|
||||||
{
|
{
|
||||||
@ -466,11 +466,12 @@ extend_bindings(StatementClass *stmt, int num_columns)
|
|||||||
|
|
||||||
stmt->bindings = new_bindings;
|
stmt->bindings = new_bindings;
|
||||||
stmt->bindings_allocated = num_columns;
|
stmt->bindings_allocated = num_columns;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* There is no reason to zero out extra bindings if there are */
|
/*
|
||||||
/* more than needed. If an app has allocated extra bindings, */
|
* There is no reason to zero out extra bindings if there are
|
||||||
/* let it worry about it by unbinding those columns. */
|
* more than needed. If an app has allocated extra bindings,
|
||||||
|
* let it worry about it by unbinding those columns.
|
||||||
|
*/
|
||||||
|
|
||||||
/* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
|
/* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
|
||||||
/* SQLExecDirect(...) # returns 5 cols */
|
/* SQLExecDirect(...) # returns 5 cols */
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* 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.
|
||||||
@ -8,7 +9,7 @@
|
|||||||
* 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"
|
||||||
@ -37,6 +38,7 @@ CI_Constructor()
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CI_Destructor(ColumnInfoClass *self)
|
CI_Destructor(ColumnInfoClass *self)
|
||||||
{
|
{
|
||||||
@ -45,9 +47,11 @@ CI_Destructor(ColumnInfoClass *self)
|
|||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read in field descriptions.
|
|
||||||
If self is not null, then also store the information.
|
/*
|
||||||
If self is null, then just read, don't store.
|
* Read in field descriptions.
|
||||||
|
* If self is not null, then also store the information.
|
||||||
|
* If self is null, then just read, don't store.
|
||||||
*/
|
*/
|
||||||
char
|
char
|
||||||
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
|
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
|
||||||
@ -71,14 +75,12 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
|
|||||||
mylog("num_fields = %d\n", new_num_fields);
|
mylog("num_fields = %d\n", new_num_fields);
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{ /* according to that allocate memory */
|
/* according to that allocate memory */
|
||||||
CI_set_num_fields(self, new_num_fields);
|
CI_set_num_fields(self, new_num_fields);
|
||||||
}
|
|
||||||
|
|
||||||
/* now read in the descriptions */
|
/* now read in the descriptions */
|
||||||
for (lf = 0; lf < new_num_fields; lf++)
|
for (lf = 0; lf < new_num_fields; lf++)
|
||||||
{
|
{
|
||||||
|
|
||||||
SOCK_get_string(sock, new_field_name, 2 * MAX_COLUMN_LEN);
|
SOCK_get_string(sock, new_field_name, 2 * MAX_COLUMN_LEN);
|
||||||
new_adtid = (Oid) SOCK_get_int(sock, 4);
|
new_adtid = (Oid) SOCK_get_int(sock, 4);
|
||||||
new_adtsize = (Int2) SOCK_get_int(sock, 2);
|
new_adtsize = (Int2) SOCK_get_int(sock, 2);
|
||||||
@ -86,7 +88,6 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
|
|||||||
/* If 6.4 protocol, then read the atttypmod field */
|
/* If 6.4 protocol, then read the atttypmod field */
|
||||||
if (PG_VERSION_GE(conn, 6.4))
|
if (PG_VERSION_GE(conn, 6.4))
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("READING ATTTYPMOD\n");
|
mylog("READING ATTTYPMOD\n");
|
||||||
new_atttypmod = (Int4) SOCK_get_int(sock, 4);
|
new_atttypmod = (Int4) SOCK_get_int(sock, 4);
|
||||||
|
|
||||||
@ -107,7 +108,6 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CI_free_memory(ColumnInfoClass *self)
|
CI_free_memory(ColumnInfoClass *self)
|
||||||
{
|
{
|
||||||
@ -143,6 +143,7 @@ CI_free_memory(ColumnInfoClass *self)
|
|||||||
self->atttypmod = NULL;
|
self->atttypmod = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
|
CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
|
||||||
{
|
{
|
||||||
@ -158,11 +159,11 @@ CI_set_num_fields(ColumnInfoClass *self, int new_num_fields)
|
|||||||
self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields);
|
self->atttypmod = (Int4 *) malloc(sizeof(Int4) * self->num_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
|
CI_set_field_info(ColumnInfoClass *self, int field_num, char *new_name,
|
||||||
Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
|
Oid new_adtid, Int2 new_adtsize, Int4 new_atttypmod)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* check bounds */
|
/* check bounds */
|
||||||
if ((field_num < 0) || (field_num >= self->num_fields))
|
if ((field_num < 0) || (field_num >= self->num_fields))
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: connection.c
|
/*------
|
||||||
|
* Module: connection.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to
|
* Description: This module contains routines related to
|
||||||
* connecting to and disconnecting from the Postgres DBMS.
|
* connecting to and disconnecting from the Postgres DBMS.
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* SQLBrowseConnect(NI)
|
* SQLBrowseConnect(NI)
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||||
|
|
||||||
@ -83,8 +84,6 @@ SQLAllocConnect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLConnect(
|
SQLConnect(
|
||||||
HDBC hdbc,
|
HDBC hdbc,
|
||||||
@ -140,7 +139,6 @@ SQLConnect(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLBrowseConnect(
|
SQLBrowseConnect(
|
||||||
@ -158,7 +156,6 @@ SQLBrowseConnect(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Drop any hstmts open on hdbc and disconnect from database */
|
/* Drop any hstmts open on hdbc and disconnect from database */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
@ -199,8 +196,6 @@ SQLDisconnect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLFreeConnect(
|
SQLFreeConnect(
|
||||||
HDBC hdbc)
|
HDBC hdbc)
|
||||||
@ -235,11 +230,8 @@ SQLFreeConnect(
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
|
||||||
* IMPLEMENTATION CONNECTION CLASS
|
* IMPLEMENTATION CONNECTION CLASS
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ConnectionClass *
|
ConnectionClass *
|
||||||
CC_Constructor()
|
CC_Constructor()
|
||||||
{
|
{
|
||||||
@ -249,7 +241,6 @@ CC_Constructor()
|
|||||||
|
|
||||||
if (rv != NULL)
|
if (rv != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
rv->henv = NULL; /* not yet associated with an environment */
|
rv->henv = NULL; /* not yet associated with an environment */
|
||||||
|
|
||||||
rv->errormsg = NULL;
|
rv->errormsg = NULL;
|
||||||
@ -301,7 +292,6 @@ CC_Constructor()
|
|||||||
char
|
char
|
||||||
CC_Destructor(ConnectionClass *self)
|
CC_Destructor(ConnectionClass *self)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("enter CC_Destructor, self=%u\n", self);
|
mylog("enter CC_Destructor, self=%u\n", self);
|
||||||
|
|
||||||
if (self->status == CONN_EXECUTING)
|
if (self->status == CONN_EXECUTING)
|
||||||
@ -343,6 +333,7 @@ CC_Destructor(ConnectionClass *self)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return how many cursors are opened on this connection */
|
/* Return how many cursors are opened on this connection */
|
||||||
int
|
int
|
||||||
CC_cursor_count(ConnectionClass *self)
|
CC_cursor_count(ConnectionClass *self)
|
||||||
@ -365,6 +356,7 @@ CC_cursor_count(ConnectionClass *self)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CC_clear_error(ConnectionClass *self)
|
CC_clear_error(ConnectionClass *self)
|
||||||
{
|
{
|
||||||
@ -373,8 +365,11 @@ CC_clear_error(ConnectionClass *self)
|
|||||||
self->errormsg_created = FALSE;
|
self->errormsg_created = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to cancel a transaction */
|
|
||||||
/* We are almost always in the middle of a transaction. */
|
/*
|
||||||
|
* Used to cancel a transaction.
|
||||||
|
* We are almost always in the middle of a transaction.
|
||||||
|
*/
|
||||||
char
|
char
|
||||||
CC_abort(ConnectionClass *self)
|
CC_abort(ConnectionClass *self)
|
||||||
{
|
{
|
||||||
@ -399,6 +394,7 @@ CC_abort(ConnectionClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is called by SQLDisconnect also */
|
/* This is called by SQLDisconnect also */
|
||||||
char
|
char
|
||||||
CC_cleanup(ConnectionClass *self)
|
CC_cleanup(ConnectionClass *self)
|
||||||
@ -434,7 +430,6 @@ CC_cleanup(ConnectionClass *self)
|
|||||||
stmt = self->stmts[i];
|
stmt = self->stmts[i];
|
||||||
if (stmt)
|
if (stmt)
|
||||||
{
|
{
|
||||||
|
|
||||||
stmt->hdbc = NULL; /* prevent any more dbase interactions */
|
stmt->hdbc = NULL; /* prevent any more dbase interactions */
|
||||||
|
|
||||||
SC_Destructor(stmt);
|
SC_Destructor(stmt);
|
||||||
@ -456,6 +451,7 @@ CC_cleanup(ConnectionClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CC_set_translation(ConnectionClass *self)
|
CC_set_translation(ConnectionClass *self)
|
||||||
{
|
{
|
||||||
@ -499,6 +495,7 @@ CC_set_translation(ConnectionClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
CC_connect(ConnectionClass *self, char do_password)
|
CC_connect(ConnectionClass *self, char do_password)
|
||||||
{
|
{
|
||||||
@ -521,7 +518,6 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
|
qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
|
||||||
POSTGRESDRIVERVERSION,
|
POSTGRESDRIVERVERSION,
|
||||||
globals.fetch_max,
|
globals.fetch_max,
|
||||||
@ -646,14 +642,13 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
mylog("gonna do authentication\n");
|
mylog("gonna do authentication\n");
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************** */
|
/*
|
||||||
/* Now get the authentication request from backend */
|
* Now get the authentication request from backend
|
||||||
/* *************************************************** */
|
*/
|
||||||
|
|
||||||
if (!PROTOCOL_62(ci))
|
if (!PROTOCOL_62(ci))
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
||||||
if (do_password)
|
if (do_password)
|
||||||
beresp = 'R';
|
beresp = 'R';
|
||||||
else
|
else
|
||||||
@ -743,8 +738,10 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
|
|
||||||
CC_clear_error(self); /* clear any password error */
|
CC_clear_error(self); /* clear any password error */
|
||||||
|
|
||||||
/* send an empty query in order to find out whether the specified */
|
/*
|
||||||
/* database really exists on the server machine */
|
* send an empty query in order to find out whether the specified
|
||||||
|
* database really exists on the server machine
|
||||||
|
*/
|
||||||
mylog("sending an empty query...\n");
|
mylog("sending an empty query...\n");
|
||||||
|
|
||||||
res = CC_send_query(self, " ", NULL);
|
res = CC_send_query(self, " ", NULL);
|
||||||
@ -764,9 +761,9 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
|
|
||||||
CC_set_translation(self);
|
CC_set_translation(self);
|
||||||
|
|
||||||
/**********************************************/
|
/*
|
||||||
/******* Send any initial settings *********/
|
* Send any initial settings
|
||||||
/**********************************************/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since these functions allocate statements, and since the connection
|
* Since these functions allocate statements, and since the connection
|
||||||
@ -789,6 +786,7 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
CC_add_statement(ConnectionClass *self, StatementClass *stmt)
|
CC_add_statement(ConnectionClass *self, StatementClass *stmt)
|
||||||
{
|
{
|
||||||
@ -821,6 +819,7 @@ CC_add_statement(ConnectionClass *self, StatementClass *stmt)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
|
CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
|
||||||
{
|
{
|
||||||
@ -838,8 +837,10 @@ CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a more informative error message by concatenating the connection
|
|
||||||
error message with its socket error message.
|
/*
|
||||||
|
* Create a more informative error message by concatenating the connection
|
||||||
|
* error message with its socket error message.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
CC_create_errormsg(ConnectionClass *self)
|
CC_create_errormsg(ConnectionClass *self)
|
||||||
@ -897,13 +898,14 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
|
/*
|
||||||
the same existing QResultClass (this occurs when the tuple cache is depleted and
|
* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
|
||||||
needs to be re-filled).
|
* the same existing QResultClass (this occurs when the tuple cache is depleted and
|
||||||
|
* needs to be re-filled).
|
||||||
The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
|
*
|
||||||
(i.e., C3326857) for SQL select statements. This cursor is then used in future
|
* The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
|
||||||
'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
|
* (i.e., C3326857) for SQL select statements. This cursor is then used in future
|
||||||
|
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
|
||||||
*/
|
*/
|
||||||
QResultClass *
|
QResultClass *
|
||||||
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
||||||
@ -915,10 +917,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
SocketClass *sock = self->sock;
|
SocketClass *sock = self->sock;
|
||||||
/* ERROR_MSG_LENGTH is suffcient */
|
/* ERROR_MSG_LENGTH is suffcient */
|
||||||
static char msgbuffer[ERROR_MSG_LENGTH + 1];
|
static char msgbuffer[ERROR_MSG_LENGTH + 1];
|
||||||
char cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
|
/* QR_set_command() dups this string so doesn't need static */
|
||||||
* this string so dont
|
char cmdbuffer[ERROR_MSG_LENGTH + 1];
|
||||||
* need static */
|
|
||||||
|
|
||||||
|
|
||||||
mylog("send_query(): conn=%u, query='%s'\n", self, query);
|
mylog("send_query(): conn=%u, query='%s'\n", self, query);
|
||||||
qlog("conn=%u, query='%s'\n", self, query);
|
qlog("conn=%u, query='%s'\n", self, query);
|
||||||
@ -1004,7 +1004,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
char clear = 0;
|
char clear = 0;
|
||||||
|
|
||||||
mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
|
mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
|
||||||
@ -1203,6 +1202,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
|
CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
|
||||||
{
|
{
|
||||||
@ -1241,7 +1241,6 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
|
|||||||
|
|
||||||
for (i = 0; i < nargs; ++i)
|
for (i = 0; i < nargs; ++i)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
|
mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
|
||||||
|
|
||||||
SOCK_put_int(sock, args[i].len, 4);
|
SOCK_put_int(sock, args[i].len, 4);
|
||||||
@ -1373,8 +1372,9 @@ CC_send_settings(ConnectionClass *self)
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/* This function must use the local odbc API functions since the odbc state
|
/*
|
||||||
has not transitioned to "connected" yet.
|
* This function must use the local odbc API functions since the odbc state
|
||||||
|
* has not transitioned to "connected" yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = SQLAllocStmt(self, &hstmt);
|
result = SQLAllocStmt(self, &hstmt);
|
||||||
@ -1457,9 +1457,11 @@ CC_send_settings(ConnectionClass *self)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is just a hack to get the oid of our Large Object oid type.
|
|
||||||
If a real Large Object oid type is made part of Postgres, this function
|
/*
|
||||||
will go away and the define 'PG_TYPE_LO' will be updated.
|
* This function is just a hack to get the oid of our Large Object oid type.
|
||||||
|
* If a real Large Object oid type is made part of Postgres, this function
|
||||||
|
* will go away and the define 'PG_TYPE_LO' will be updated.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
CC_lookup_lo(ConnectionClass *self)
|
CC_lookup_lo(ConnectionClass *self)
|
||||||
@ -1471,8 +1473,9 @@ CC_lookup_lo(ConnectionClass *self)
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/* This function must use the local odbc API functions since the odbc state
|
/*
|
||||||
has not transitioned to "connected" yet.
|
* This function must use the local odbc API functions since the odbc state
|
||||||
|
* has not transitioned to "connected" yet.
|
||||||
*/
|
*/
|
||||||
result = SQLAllocStmt(self, &hstmt);
|
result = SQLAllocStmt(self, &hstmt);
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
@ -1506,9 +1509,11 @@ CC_lookup_lo(ConnectionClass *self)
|
|||||||
result = SQLFreeStmt(hstmt, SQL_DROP);
|
result = SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function initializes the version of PostgreSQL from
|
|
||||||
connInfo.protocol that we're connected to.
|
/*
|
||||||
h-inoue 01-2-2001
|
* This function initializes the version of PostgreSQL from
|
||||||
|
* connInfo.protocol that we're connected to.
|
||||||
|
* h-inoue 01-2-2001
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
CC_initialize_pg_version(ConnectionClass *self)
|
CC_initialize_pg_version(ConnectionClass *self)
|
||||||
@ -1534,9 +1539,11 @@ CC_initialize_pg_version(ConnectionClass *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function gets the version of PostgreSQL that we're connected to.
|
|
||||||
This is used to return the correct info in SQLGetInfo
|
/*
|
||||||
DJP - 25-1-2001
|
* This function gets the version of PostgreSQL that we're connected to.
|
||||||
|
* This is used to return the correct info in SQLGetInfo
|
||||||
|
* DJP - 25-1-2001
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
CC_lookup_pg_version(ConnectionClass *self)
|
CC_lookup_pg_version(ConnectionClass *self)
|
||||||
@ -1551,8 +1558,9 @@ CC_lookup_pg_version(ConnectionClass *self)
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/* This function must use the local odbc API functions since the odbc state
|
/*
|
||||||
has not transitioned to "connected" yet.
|
* This function must use the local odbc API functions since the odbc state
|
||||||
|
* has not transitioned to "connected" yet.
|
||||||
*/
|
*/
|
||||||
result = SQLAllocStmt(self, &hstmt);
|
result = SQLAllocStmt(self, &hstmt);
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
@ -1581,8 +1589,10 @@ CC_lookup_pg_version(ConnectionClass *self)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the Major and Minor numbers from the string. */
|
/*
|
||||||
/* This assumes the string starts 'Postgresql X.X' */
|
* Extract the Major and Minor numbers from the string.
|
||||||
|
* This assumes the string starts 'Postgresql X.X'
|
||||||
|
*/
|
||||||
strcpy(szVersion, "0.0");
|
strcpy(szVersion, "0.0");
|
||||||
if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
|
if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
|
||||||
{
|
{
|
||||||
@ -1600,6 +1610,7 @@ CC_lookup_pg_version(ConnectionClass *self)
|
|||||||
result = SQLFreeStmt(hstmt, SQL_DROP);
|
result = SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CC_log_error(char *func, char *desc, ConnectionClass *self)
|
CC_log_error(char *func, char *desc, ConnectionClass *self)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: convert.c
|
/*-------
|
||||||
|
* Module: convert.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to
|
* Description: This module contains routines related to
|
||||||
* converting parameters and columns into requested data types.
|
* converting parameters and columns into requested data types.
|
||||||
@ -12,7 +13,7 @@
|
|||||||
* API functions: none
|
* API functions: none
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||||
|
|
||||||
@ -64,9 +65,9 @@ typedef signed char SCHAR;
|
|||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
/* How to map ODBC scalar functions {fn func(args)} to Postgres
|
/*
|
||||||
* This is just a simple substitution
|
* How to map ODBC scalar functions {fn func(args)} to Postgres.
|
||||||
* List augmented from
|
* This is just a simple substitution. List augmented from:
|
||||||
* http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
|
* http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
|
||||||
* - thomas 2000-04-03
|
* - thomas 2000-04-03
|
||||||
*/
|
*/
|
||||||
@ -141,21 +142,24 @@ unsigned int conv_from_octal(unsigned char *s);
|
|||||||
unsigned int conv_from_hex(unsigned char *s);
|
unsigned int conv_from_hex(unsigned char *s);
|
||||||
char *conv_to_octal(unsigned char val);
|
char *conv_to_octal(unsigned char val);
|
||||||
|
|
||||||
/******** A Guide for date/time/timestamp conversions **************
|
/*---------
|
||||||
|
* A Guide for date/time/timestamp conversions
|
||||||
|
*
|
||||||
|
* field_type fCType Output
|
||||||
|
* ---------- ------ ----------
|
||||||
|
* PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE
|
||||||
|
* PG_TYPE_DATE SQL_C_DATE SQL_C_DATE
|
||||||
|
* PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight))
|
||||||
|
* PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME
|
||||||
|
* PG_TYPE_TIME SQL_C_TIME SQL_C_TIME
|
||||||
|
* PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date)
|
||||||
|
* PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP
|
||||||
|
* PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated)
|
||||||
|
* PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated)
|
||||||
|
* PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP
|
||||||
|
*---------
|
||||||
|
*/
|
||||||
|
|
||||||
field_type fCType Output
|
|
||||||
---------- ------ ----------
|
|
||||||
PG_TYPE_DATE SQL_C_DEFAULT SQL_C_DATE
|
|
||||||
PG_TYPE_DATE SQL_C_DATE SQL_C_DATE
|
|
||||||
PG_TYPE_DATE SQL_C_TIMESTAMP SQL_C_TIMESTAMP (time = 0 (midnight))
|
|
||||||
PG_TYPE_TIME SQL_C_DEFAULT SQL_C_TIME
|
|
||||||
PG_TYPE_TIME SQL_C_TIME SQL_C_TIME
|
|
||||||
PG_TYPE_TIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP (date = current date)
|
|
||||||
PG_TYPE_ABSTIME SQL_C_DEFAULT SQL_C_TIMESTAMP
|
|
||||||
PG_TYPE_ABSTIME SQL_C_DATE SQL_C_DATE (time is truncated)
|
|
||||||
PG_TYPE_ABSTIME SQL_C_TIME SQL_C_TIME (date is truncated)
|
|
||||||
PG_TYPE_ABSTIME SQL_C_TIMESTAMP SQL_C_TIMESTAMP
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* This is called by SQLFetch() */
|
/* This is called by SQLFetch() */
|
||||||
@ -168,6 +172,7 @@ copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *val
|
|||||||
(SDWORD) bic->buflen, (SDWORD *) bic->used);
|
(SDWORD) bic->buflen, (SDWORD *) bic->used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is called by SQLGetData() */
|
/* This is called by SQLGetData() */
|
||||||
int
|
int
|
||||||
copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
|
copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
|
||||||
@ -187,17 +192,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
int result = COPY_OK;
|
int result = COPY_OK;
|
||||||
char tempBuf[TEXT_FIELD_SIZE + 5];
|
char tempBuf[TEXT_FIELD_SIZE + 5];
|
||||||
|
|
||||||
/* rgbValueOffset is *ONLY* for character and binary data */
|
/*---------
|
||||||
/* pcbValueOffset is for computing any pcbValue location */
|
* rgbValueOffset is *ONLY* for character and binary data.
|
||||||
|
* pcbValueOffset is for computing any pcbValue location
|
||||||
|
*---------
|
||||||
|
*/
|
||||||
|
|
||||||
if (bind_size > 0)
|
if (bind_size > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
|
pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
pcbValueOffset = bind_row * sizeof(SDWORD);
|
pcbValueOffset = bind_row * sizeof(SDWORD);
|
||||||
rgbValueOffset = bind_row * cbValueMax;
|
rgbValueOffset = bind_row * cbValueMax;
|
||||||
|
|
||||||
@ -215,14 +221,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
|
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
/* handle a null just by returning SQL_NULL_DATA in pcbValue, */
|
/*
|
||||||
/* and doing nothing to the buffer. */
|
* handle a null just by returning SQL_NULL_DATA in pcbValue,
|
||||||
|
* and doing nothing to the buffer.
|
||||||
|
*/
|
||||||
if (pcbValue)
|
if (pcbValue)
|
||||||
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
|
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
|
||||||
return COPY_OK;
|
return COPY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (stmt->hdbc->DataSourceToDriver != NULL)
|
if (stmt->hdbc->DataSourceToDriver != NULL)
|
||||||
{
|
{
|
||||||
int length = strlen(value);
|
int length = strlen(value);
|
||||||
@ -234,17 +241,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/********************************************************************
|
* First convert any specific postgres types into more
|
||||||
First convert any specific postgres types into more
|
* useable data.
|
||||||
useable data.
|
*
|
||||||
|
* NOTE: Conversions from PG char/varchar of a date/time/timestamp
|
||||||
NOTE: Conversions from PG char/varchar of a date/time/timestamp
|
* value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
|
||||||
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
|
*/
|
||||||
*********************************************************************/
|
|
||||||
switch (field_type)
|
switch (field_type)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $$$ need to add parsing for date/time/timestamp strings in
|
* $$$ need to add parsing for date/time/timestamp strings in
|
||||||
* PG_TYPE_CHAR,VARCHAR $$$
|
* PG_TYPE_CHAR,VARCHAR $$$
|
||||||
@ -261,13 +266,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
case PG_TYPE_DATETIME:
|
case PG_TYPE_DATETIME:
|
||||||
case PG_TYPE_TIMESTAMP:
|
case PG_TYPE_TIMESTAMP:
|
||||||
if (strnicmp(value, "invalid", 7) != 0)
|
if (strnicmp(value, "invalid", 7) != 0)
|
||||||
{
|
|
||||||
sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
|
sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m, &st.d, &st.hh, &st.mm, &st.ss);
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{ /* The timestamp is invalid so set
|
{
|
||||||
* something conspicuous, like the epoch */
|
/*
|
||||||
|
* The timestamp is invalid so set
|
||||||
|
* something conspicuous, like the epoch
|
||||||
|
*/
|
||||||
t = 0;
|
t = 0;
|
||||||
tim = localtime(&t);
|
tim = localtime(&t);
|
||||||
st.m = tim->tm_mon + 1;
|
st.m = tim->tm_mon + 1;
|
||||||
@ -369,15 +374,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
|
mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
|
rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
|
||||||
|
|
||||||
if (fCType == SQL_C_CHAR)
|
if (fCType == SQL_C_CHAR)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/* Special character formatting as required */
|
/* Special character formatting as required */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These really should return error if cbValueMax is not big
|
* These really should return error if cbValueMax is not big
|
||||||
* enough.
|
* enough.
|
||||||
@ -456,7 +457,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
|
|
||||||
if (cbValueMax > 0)
|
if (cbValueMax > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
|
copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
|
||||||
|
|
||||||
/* Copy the data */
|
/* Copy the data */
|
||||||
@ -483,7 +483,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for SQL_C_CHAR, it's probably ok to leave currency symbols in.
|
* for SQL_C_CHAR, it's probably ok to leave currency symbols in.
|
||||||
* But to convert to numeric types, it is necessary to get rid of
|
* But to convert to numeric types, it is necessary to get rid of
|
||||||
@ -633,7 +632,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
|
|
||||||
if (stmt->current_col >= 0)
|
if (stmt->current_col >= 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* No more data left for this column */
|
/* No more data left for this column */
|
||||||
if (stmt->bindings[stmt->current_col].data_left == 0)
|
if (stmt->bindings[stmt->current_col].data_left == 0)
|
||||||
return COPY_NO_DATA_FOUND;
|
return COPY_NO_DATA_FOUND;
|
||||||
@ -690,9 +688,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function inserts parameters into an SQL statements.
|
/*
|
||||||
It will also modify a SELECT statement for use with declare/fetch cursors.
|
* This function inserts parameters into an SQL statements.
|
||||||
This function no longer does any dynamic memory allocation!
|
* It will also modify a SELECT statement for use with declare/fetch cursors.
|
||||||
|
* This function no longer does any dynamic memory allocation!
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
copy_statement_with_parameters(StatementClass *stmt)
|
copy_statement_with_parameters(StatementClass *stmt)
|
||||||
@ -760,7 +759,6 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
|
|
||||||
for (opos = 0; opos < oldstmtlen; opos++)
|
for (opos = 0; opos < oldstmtlen; opos++)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Squeeze carriage-return/linefeed pairs to linefeed only */
|
/* Squeeze carriage-return/linefeed pairs to linefeed only */
|
||||||
if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen &&
|
if (old_statement[opos] == '\r' && opos + 1 < oldstmtlen &&
|
||||||
old_statement[opos + 1] == '\n')
|
old_statement[opos + 1] == '\n')
|
||||||
@ -782,10 +780,8 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
|
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
char *end = multibyte_strchr(begin, '}');
|
char *end = multibyte_strchr(begin, '}');
|
||||||
|
|
||||||
#else
|
#else
|
||||||
char *end = strchr(begin, '}');
|
char *end = strchr(begin, '}');
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!end)
|
if (!end)
|
||||||
@ -807,12 +803,9 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
opos += end - begin + 1;
|
opos += end - begin + 1;
|
||||||
|
|
||||||
*end = '}';
|
*end = '}';
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Can you have parameter markers inside of quotes? I dont think
|
* Can you have parameter markers inside of quotes? I dont think
|
||||||
* so. All the queries I've seen expect the driver to put quotes
|
* so. All the queries I've seen expect the driver to put quotes
|
||||||
@ -829,12 +822,9 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Its a '?' parameter alright
|
||||||
/****************************************************/
|
*/
|
||||||
/* Its a '?' parameter alright */
|
|
||||||
/****************************************************/
|
|
||||||
|
|
||||||
param_number++;
|
param_number++;
|
||||||
|
|
||||||
if (param_number >= stmt->parameters_allocated)
|
if (param_number >= stmt->parameters_allocated)
|
||||||
@ -906,7 +896,6 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
param_string[0] = '\0';
|
param_string[0] = '\0';
|
||||||
cbuf[0] = '\0';
|
cbuf[0] = '\0';
|
||||||
|
|
||||||
|
|
||||||
/* Convert input C type to a neutral format */
|
/* Convert input C type to a neutral format */
|
||||||
switch (param_ctype)
|
switch (param_ctype)
|
||||||
{
|
{
|
||||||
@ -1113,13 +1102,10 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
|
|
||||||
if (stmt->parameters[param_number].data_at_exec)
|
if (stmt->parameters[param_number].data_at_exec)
|
||||||
{
|
{
|
||||||
|
|
||||||
lobj_oid = stmt->parameters[param_number].lobj_oid;
|
lobj_oid = stmt->parameters[param_number].lobj_oid;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/* begin transaction if needed */
|
/* begin transaction if needed */
|
||||||
if (!CC_is_in_trans(stmt->hdbc))
|
if (!CC_is_in_trans(stmt->hdbc))
|
||||||
{
|
{
|
||||||
@ -1264,15 +1250,12 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
new_statement[npos++] = '\''; /* Close Quote */
|
new_statement[npos++] = '\''; /* Close Quote */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end, for */
|
} /* end, for */
|
||||||
|
|
||||||
/* make sure new_statement is always null-terminated */
|
/* make sure new_statement is always null-terminated */
|
||||||
new_statement[npos] = '\0';
|
new_statement[npos] = '\0';
|
||||||
|
|
||||||
|
|
||||||
if (stmt->hdbc->DriverToDataSource != NULL)
|
if (stmt->hdbc->DriverToDataSource != NULL)
|
||||||
{
|
{
|
||||||
int length = strlen(new_statement);
|
int length = strlen(new_statement);
|
||||||
@ -1284,10 +1267,10 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
mapFunction(char *func)
|
mapFunction(char *func)
|
||||||
{
|
{
|
||||||
@ -1300,7 +1283,10 @@ mapFunction(char *func)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert_escape()
|
|
||||||
|
/*
|
||||||
|
* convert_escape()
|
||||||
|
*
|
||||||
* This function returns a pointer to static memory!
|
* This function returns a pointer to static memory!
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
@ -1330,7 +1316,6 @@ convert_escape(char *value)
|
|||||||
}
|
}
|
||||||
else if (strcmp(key, "fn") == 0)
|
else if (strcmp(key, "fn") == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function invocation Separate off the func name, skipping
|
* Function invocation Separate off the func name, skipping
|
||||||
* trailing whitespace.
|
* trailing whitespace.
|
||||||
@ -1381,7 +1366,6 @@ convert_escape(char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return escape;
|
return escape;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1405,9 +1389,10 @@ convert_money(char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/* This function parses a character string for date/time info and fills in SIMPLE_TIME */
|
* This function parses a character string for date/time info and fills in SIMPLE_TIME
|
||||||
/* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */
|
* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
|
||||||
|
*/
|
||||||
char
|
char
|
||||||
parse_datetime(char *buf, SIMPLE_TIME *st)
|
parse_datetime(char *buf, SIMPLE_TIME *st)
|
||||||
{
|
{
|
||||||
@ -1465,6 +1450,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Change linefeed to carriage-return/linefeed */
|
/* Change linefeed to carriage-return/linefeed */
|
||||||
int
|
int
|
||||||
convert_linefeeds(char *si, char *dst, size_t max)
|
convert_linefeeds(char *si, char *dst, size_t max)
|
||||||
@ -1493,8 +1479,10 @@ convert_linefeeds(char *si, char *dst, size_t max)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change carriage-return/linefeed to just linefeed
|
|
||||||
Plus, escape any special characters.
|
/*
|
||||||
|
* Change carriage-return/linefeed to just linefeed
|
||||||
|
* Plus, escape any special characters.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
convert_special_chars(char *si, char *dst, int used)
|
convert_special_chars(char *si, char *dst, int used)
|
||||||
@ -1537,6 +1525,7 @@ convert_special_chars(char *si, char *dst, int used)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* !!! Need to implement this function !!! */
|
/* !!! Need to implement this function !!! */
|
||||||
int
|
int
|
||||||
convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
|
convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
|
||||||
@ -1547,6 +1536,7 @@ convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
conv_from_octal(unsigned char *s)
|
conv_from_octal(unsigned char *s)
|
||||||
{
|
{
|
||||||
@ -1560,6 +1550,7 @@ conv_from_octal(unsigned char *s)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
conv_from_hex(unsigned char *s)
|
conv_from_hex(unsigned char *s)
|
||||||
{
|
{
|
||||||
@ -1569,7 +1560,6 @@ conv_from_hex(unsigned char *s)
|
|||||||
|
|
||||||
for (i = 1; i <= 2; i++)
|
for (i = 1; i <= 2; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (s[i] >= 'a' && s[i] <= 'f')
|
if (s[i] >= 'a' && s[i] <= 'f')
|
||||||
val = s[i] - 'a' + 10;
|
val = s[i] - 'a' + 10;
|
||||||
else if (s[i] >= 'A' && s[i] <= 'F')
|
else if (s[i] >= 'A' && s[i] <= 'F')
|
||||||
@ -1583,6 +1573,7 @@ conv_from_hex(unsigned char *s)
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* convert octal escapes to bytes */
|
/* convert octal escapes to bytes */
|
||||||
int
|
int
|
||||||
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
|
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
|
||||||
@ -1629,6 +1620,7 @@ conv_to_octal(unsigned char val)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* convert non-ascii bytes to octal escape sequences */
|
/* convert non-ascii bytes to octal escape sequences */
|
||||||
int
|
int
|
||||||
convert_to_pgbinary(unsigned char *in, char *out, int len)
|
convert_to_pgbinary(unsigned char *in, char *out, int len)
|
||||||
@ -1636,7 +1628,6 @@ convert_to_pgbinary(unsigned char *in, char *out, int len)
|
|||||||
int i,
|
int i,
|
||||||
o = 0;
|
o = 0;
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
|
mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
|
||||||
@ -1647,7 +1638,6 @@ convert_to_pgbinary(unsigned char *in, char *out, int len)
|
|||||||
strcpy(&out[o], conv_to_octal(in[i]));
|
strcpy(&out[o], conv_to_octal(in[i]));
|
||||||
o += 5;
|
o += 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
|
mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
|
||||||
@ -1705,20 +1695,21 @@ decode(char *in, char *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------
|
||||||
/* 1. get oid (from 'value')
|
* 1. get oid (from 'value')
|
||||||
2. open the large object
|
* 2. open the large object
|
||||||
3. read from the large object (handle multiple GetData)
|
* 3. read from the large object (handle multiple GetData)
|
||||||
4. close when read less than requested? -OR-
|
* 4. close when read less than requested? -OR-
|
||||||
lseek/read each time
|
* lseek/read each time
|
||||||
handle case where application receives truncated and
|
* handle case where application receives truncated and
|
||||||
decides not to continue reading.
|
* decides not to continue reading.
|
||||||
|
*
|
||||||
CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
|
* CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
|
||||||
data type currently mapped to a PG_TYPE_LO. But, if any other types
|
* data type currently mapped to a PG_TYPE_LO. But, if any other types
|
||||||
are desired to map to a large object (PG_TYPE_LO), then that would
|
* are desired to map to a large object (PG_TYPE_LO), then that would
|
||||||
need to be handled here. For example, LONGVARCHAR could possibly be
|
* need to be handled here. For example, LONGVARCHAR could possibly be
|
||||||
mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
|
* mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
|
||||||
|
*-------
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
||||||
@ -1745,7 +1736,6 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
|||||||
|
|
||||||
if (!bindInfo || bindInfo->data_left == -1)
|
if (!bindInfo || bindInfo->data_left == -1)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* begin transaction if needed */
|
/* begin transaction if needed */
|
||||||
if (!CC_is_in_trans(stmt->hdbc))
|
if (!CC_is_in_trans(stmt->hdbc))
|
||||||
{
|
{
|
||||||
@ -1784,7 +1774,6 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
|||||||
retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
|
retval = lo_lseek(stmt->hdbc, stmt->lobj_fd, 0L, SEEK_END);
|
||||||
if (retval >= 0)
|
if (retval >= 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
left = lo_tell(stmt->hdbc, stmt->lobj_fd);
|
left = lo_tell(stmt->hdbc, stmt->lobj_fd);
|
||||||
if (bindInfo)
|
if (bindInfo)
|
||||||
bindInfo->data_left = left;
|
bindInfo->data_left = left;
|
||||||
@ -1849,11 +1838,9 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
|||||||
if (pcbValue)
|
if (pcbValue)
|
||||||
*pcbValue = left < 0 ? SQL_NO_TOTAL : left;
|
*pcbValue = left < 0 ? SQL_NO_TOTAL : left;
|
||||||
|
|
||||||
|
|
||||||
if (bindInfo && bindInfo->data_left > 0)
|
if (bindInfo && bindInfo->data_left > 0)
|
||||||
bindInfo->data_left -= retval;
|
bindInfo->data_left -= retval;
|
||||||
|
|
||||||
|
|
||||||
if (!bindInfo || bindInfo->data_left == 0)
|
if (!bindInfo || bindInfo->data_left == 0)
|
||||||
{
|
{
|
||||||
lo_close(stmt->hdbc, stmt->lobj_fd);
|
lo_close(stmt->hdbc, stmt->lobj_fd);
|
||||||
@ -1886,7 +1873,5 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
|||||||
stmt->lobj_fd = -1; /* prevent further reading */
|
stmt->lobj_fd = -1; /* prevent further reading */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: dlg_specific.c
|
/*-------
|
||||||
|
* Module: dlg_specific.c
|
||||||
*
|
*
|
||||||
* Description: This module contains any specific code for handling
|
* Description: This module contains any specific code for handling
|
||||||
* dialog boxes such as driver/datasource options. Both the
|
* dialog boxes such as driver/datasource options. Both the
|
||||||
@ -12,7 +13,7 @@
|
|||||||
* API functions: none
|
* API functions: none
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||||
|
|
||||||
@ -50,11 +51,11 @@
|
|||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
void
|
void
|
||||||
SetDlgStuff(HWND hdlg, ConnInfo *ci)
|
SetDlgStuff(HWND hdlg, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If driver attribute NOT present, then set the datasource name and
|
* If driver attribute NOT present, then set the datasource name and
|
||||||
* description
|
* description
|
||||||
@ -72,6 +73,7 @@ SetDlgStuff(HWND hdlg, ConnInfo *ci)
|
|||||||
SetDlgItemText(hdlg, IDC_PORT, ci->port);
|
SetDlgItemText(hdlg, IDC_PORT, ci->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GetDlgStuff(HWND hdlg, ConnInfo *ci)
|
GetDlgStuff(HWND hdlg, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
@ -85,7 +87,6 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int CALLBACK
|
int CALLBACK
|
||||||
driver_optionsProc(HWND hdlg,
|
driver_optionsProc(HWND hdlg,
|
||||||
WORD wMsg,
|
WORD wMsg,
|
||||||
@ -141,7 +142,6 @@ driver_optionsProc(HWND hdlg,
|
|||||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||||
{
|
{
|
||||||
case IDOK:
|
case IDOK:
|
||||||
|
|
||||||
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
|
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
|
||||||
globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
|
globals.disable_optimizer = IsDlgButtonChecked(hdlg, DRV_OPTIMIZER);
|
||||||
globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
|
globals.ksqo = IsDlgButtonChecked(hdlg, DRV_KSQO);
|
||||||
@ -228,12 +228,12 @@ driver_optionsProc(HWND hdlg,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CALLBACK
|
int CALLBACK
|
||||||
ds_optionsProc(HWND hdlg,
|
ds_optionsProc(HWND hdlg,
|
||||||
WORD wMsg,
|
WORD wMsg,
|
||||||
@ -270,8 +270,6 @@ ds_optionsProc(HWND hdlg,
|
|||||||
/* latest */
|
/* latest */
|
||||||
CheckDlgButton(hdlg, DS_PG64, 1);
|
CheckDlgButton(hdlg, DS_PG64, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
|
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
|
||||||
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
|
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
|
||||||
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
|
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
|
||||||
@ -283,7 +281,6 @@ ds_optionsProc(HWND hdlg,
|
|||||||
SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings);
|
SetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||||
{
|
{
|
||||||
@ -292,9 +289,7 @@ ds_optionsProc(HWND hdlg,
|
|||||||
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
|
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), IsDlgButtonChecked(hdlg, DS_SHOWOIDCOLUMN));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
|
||||||
case IDOK:
|
case IDOK:
|
||||||
|
|
||||||
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
||||||
mylog("IDOK: got ci = %u\n", ci);
|
mylog("IDOK: got ci = %u\n", ci);
|
||||||
|
|
||||||
@ -321,7 +316,6 @@ ds_optionsProc(HWND hdlg,
|
|||||||
/* Datasource Connection Settings */
|
/* Datasource Connection Settings */
|
||||||
GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings));
|
GetDlgItemText(hdlg, DS_CONNSETTINGS, ci->conn_settings, sizeof(ci->conn_settings));
|
||||||
|
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
@ -335,6 +329,7 @@ ds_optionsProc(HWND hdlg,
|
|||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
makeConnectString(char *connect_string, ConnInfo *ci)
|
makeConnectString(char *connect_string, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
@ -365,10 +360,10 @@ makeConnectString(char *connect_string, ConnInfo *ci)
|
|||||||
encoded_conn_settings);
|
encoded_conn_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stricmp(attribute, "DSN") == 0)
|
if (stricmp(attribute, "DSN") == 0)
|
||||||
strcpy(ci->dsn, value);
|
strcpy(ci->dsn, value);
|
||||||
|
|
||||||
@ -415,9 +410,9 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings);
|
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s', conn_settings='%s')\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
getDSNdefaults(ConnInfo *ci)
|
getDSNdefaults(ConnInfo *ci)
|
||||||
{
|
{
|
||||||
@ -450,8 +445,10 @@ getDSNinfo(ConnInfo *ci, char overwrite)
|
|||||||
char *DSN = ci->dsn;
|
char *DSN = ci->dsn;
|
||||||
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
||||||
|
|
||||||
/* If a driver keyword was present, then dont use a DSN and return. */
|
/*
|
||||||
/* If DSN is null and no driver, then use the default datasource. */
|
* If a driver keyword was present, then dont use a DSN and return.
|
||||||
|
* If DSN is null and no driver, then use the default datasource.
|
||||||
|
*/
|
||||||
if (DSN[0] == '\0')
|
if (DSN[0] == '\0')
|
||||||
{
|
{
|
||||||
if (ci->driver[0] != '\0')
|
if (ci->driver[0] != '\0')
|
||||||
@ -514,11 +511,9 @@ getDSNinfo(ConnInfo *ci, char overwrite)
|
|||||||
if (ci->translation_option[0] == '\0' || overwrite)
|
if (ci->translation_option[0] == '\0' || overwrite)
|
||||||
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
|
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
|
||||||
|
|
||||||
|
|
||||||
/* Allow override of odbcinst.ini parameters here */
|
/* Allow override of odbcinst.ini parameters here */
|
||||||
getGlobalDefaults(DSN, ODBC_INI, TRUE);
|
getGlobalDefaults(DSN, ODBC_INI, TRUE);
|
||||||
|
|
||||||
|
|
||||||
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
|
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
|
||||||
DSN,
|
DSN,
|
||||||
ci->server,
|
ci->server,
|
||||||
@ -546,7 +541,6 @@ getDSNinfo(ConnInfo *ci, char overwrite)
|
|||||||
qlog(" translation_dll='%s',translation_option='%s'\n",
|
qlog(" translation_dll='%s',translation_option='%s'\n",
|
||||||
ci->translation_dll,
|
ci->translation_dll,
|
||||||
ci->translation_option);
|
ci->translation_option);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -626,15 +620,15 @@ writeDSNinfo(ConnInfo *ci)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function reads the ODBCINST.INI portion of
|
/*
|
||||||
the registry and gets any driver defaults.
|
* This function reads the ODBCINST.INI portion of
|
||||||
|
* the registry and gets any driver defaults.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
getGlobalDefaults(char *section, char *filename, char override)
|
getGlobalDefaults(char *section, char *filename, char override)
|
||||||
{
|
{
|
||||||
char temp[256];
|
char temp[256];
|
||||||
|
|
||||||
|
|
||||||
/* Fetch Count is stored in driver section */
|
/* Fetch Count is stored in driver section */
|
||||||
SQLGetPrivateProfileString(section, INI_FETCH, "",
|
SQLGetPrivateProfileString(section, INI_FETCH, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -648,7 +642,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.fetch_max = FETCH_MAX;
|
globals.fetch_max = FETCH_MAX;
|
||||||
|
|
||||||
|
|
||||||
/* Socket Buffersize is stored in driver section */
|
/* Socket Buffersize is stored in driver section */
|
||||||
SQLGetPrivateProfileString(section, INI_SOCKET, "",
|
SQLGetPrivateProfileString(section, INI_SOCKET, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -657,7 +650,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.socket_buffersize = SOCK_BUFFER_SIZE;
|
globals.socket_buffersize = SOCK_BUFFER_SIZE;
|
||||||
|
|
||||||
|
|
||||||
/* Debug is stored in the driver section */
|
/* Debug is stored in the driver section */
|
||||||
SQLGetPrivateProfileString(section, INI_DEBUG, "",
|
SQLGetPrivateProfileString(section, INI_DEBUG, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -666,7 +658,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.debug = DEFAULT_DEBUG;
|
globals.debug = DEFAULT_DEBUG;
|
||||||
|
|
||||||
|
|
||||||
/* CommLog is stored in the driver section */
|
/* CommLog is stored in the driver section */
|
||||||
SQLGetPrivateProfileString(section, INI_COMMLOG, "",
|
SQLGetPrivateProfileString(section, INI_COMMLOG, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -675,7 +666,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.commlog = DEFAULT_COMMLOG;
|
globals.commlog = DEFAULT_COMMLOG;
|
||||||
|
|
||||||
|
|
||||||
/* Optimizer is stored in the driver section only */
|
/* Optimizer is stored in the driver section only */
|
||||||
SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
|
SQLGetPrivateProfileString(section, INI_OPTIMIZER, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -734,8 +724,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
|
globals.cancel_as_freestmt = DEFAULT_CANCELASFREESTMT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* UseDeclareFetch is stored in the driver section only */
|
/* UseDeclareFetch is stored in the driver section only */
|
||||||
SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
|
SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -744,7 +732,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
else if (!override)
|
else if (!override)
|
||||||
globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
|
globals.use_declarefetch = DEFAULT_USEDECLAREFETCH;
|
||||||
|
|
||||||
|
|
||||||
/* Max Varchar Size */
|
/* Max Varchar Size */
|
||||||
SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
|
SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, "",
|
||||||
temp, sizeof(temp), filename);
|
temp, sizeof(temp), filename);
|
||||||
@ -804,7 +791,6 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
/* Dont allow override of an override! */
|
/* Dont allow override of an override! */
|
||||||
if (!override)
|
if (!override)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ConnSettings is stored in the driver section and per datasource
|
* ConnSettings is stored in the driver section and per datasource
|
||||||
* for override
|
* for override
|
||||||
@ -831,13 +817,13 @@ getGlobalDefaults(char *section, char *filename, char override)
|
|||||||
strcpy(globals.protocol, temp);
|
strcpy(globals.protocol, temp);
|
||||||
else
|
else
|
||||||
strcpy(globals.protocol, DEFAULT_PROTOCOL);
|
strcpy(globals.protocol, DEFAULT_PROTOCOL);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function writes any global parameters (that can be manipulated)
|
/*
|
||||||
to the ODBCINST.INI portion of the registry
|
* This function writes any global parameters (that can be manipulated)
|
||||||
|
* to the ODBCINST.INI portion of the registry
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
updateGlobals(void)
|
updateGlobals(void)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* 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.
|
||||||
@ -8,7 +9,7 @@
|
|||||||
* API functions: SQLDriverConnect
|
* API functions: SQLDriverConnect
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -110,9 +111,11 @@ SQLDriverConnect(
|
|||||||
/* Parse the connect string and fill in conninfo for this hdbc. */
|
/* Parse the connect string and fill in conninfo for this hdbc. */
|
||||||
dconn_get_connect_attributes(connStrIn, ci);
|
dconn_get_connect_attributes(connStrIn, ci);
|
||||||
|
|
||||||
/* If the ConnInfo in the hdbc is missing anything, */
|
/*
|
||||||
/* this function will fill them in from the registry (assuming */
|
* If the ConnInfo in the hdbc is missing anything,
|
||||||
/* of course there is a DSN given -- if not, it does nothing!) */
|
* this function will fill them in from the registry (assuming
|
||||||
|
* of course there is a DSN given -- if not, it does nothing!)
|
||||||
|
*/
|
||||||
getDSNinfo(ci, 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. */
|
||||||
@ -147,7 +150,6 @@ dialog:
|
|||||||
ci->port[0] == '\0' ||
|
ci->port[0] == '\0' ||
|
||||||
password_required)
|
password_required)
|
||||||
{
|
{
|
||||||
|
|
||||||
dialog_result = dconn_DoDialog(hwnd, ci);
|
dialog_result = dconn_DoDialog(hwnd, ci);
|
||||||
if (dialog_result != SQL_SUCCESS)
|
if (dialog_result != SQL_SUCCESS)
|
||||||
return dialog_result;
|
return dialog_result;
|
||||||
@ -178,7 +180,6 @@ dialog:
|
|||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* do the actual connect */
|
/* do the actual connect */
|
||||||
retval = CC_connect(conn, password_required);
|
retval = CC_connect(conn, password_required);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
@ -206,9 +207,9 @@ dialog:
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************/
|
/*
|
||||||
/* Create the Output Connection String */
|
* Create the Output Connection String
|
||||||
/*********************************************/
|
*/
|
||||||
result = SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
|
|
||||||
makeConnectString(connStrOut, ci);
|
makeConnectString(connStrOut, ci);
|
||||||
@ -216,7 +217,6 @@ dialog:
|
|||||||
|
|
||||||
if (szConnStrOut)
|
if (szConnStrOut)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the completed string to the caller. The correct method
|
* Return the completed string to the caller. The correct method
|
||||||
* is to only construct the connect string if a dialog was put up,
|
* is to only construct the connect string if a dialog was put up,
|
||||||
@ -247,6 +247,7 @@ dialog:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
RETCODE
|
RETCODE
|
||||||
dconn_DoDialog(HWND hwnd, ConnInfo *ci)
|
dconn_DoDialog(HWND hwnd, ConnInfo *ci)
|
||||||
@ -296,7 +297,6 @@ dconn_FDriverConnectProc(
|
|||||||
|
|
||||||
SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for
|
SetWindowLong(hdlg, DWL_USER, lParam); /* Save the ConnInfo for
|
||||||
* the "OK" */
|
* the "OK" */
|
||||||
|
|
||||||
SetDlgStuff(hdlg, ci);
|
SetDlgStuff(hdlg, ci);
|
||||||
|
|
||||||
if (ci->database[0] == '\0')
|
if (ci->database[0] == '\0')
|
||||||
@ -309,38 +309,29 @@ dconn_FDriverConnectProc(
|
|||||||
SetFocus(GetDlgItem(hdlg, IDC_USER));
|
SetFocus(GetDlgItem(hdlg, IDC_USER));
|
||||||
else if (ci->focus_password)
|
else if (ci->focus_password)
|
||||||
SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
|
SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||||
{
|
{
|
||||||
case IDOK:
|
case IDOK:
|
||||||
|
|
||||||
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
||||||
|
|
||||||
GetDlgStuff(hdlg, ci);
|
GetDlgStuff(hdlg, ci);
|
||||||
|
|
||||||
|
|
||||||
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:
|
case IDC_DRIVER:
|
||||||
|
|
||||||
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
|
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
|
||||||
hdlg, driver_optionsProc, (LPARAM) NULL);
|
hdlg, driver_optionsProc, (LPARAM) NULL);
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_DATASOURCE:
|
case IDC_DATASOURCE:
|
||||||
|
|
||||||
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
|
||||||
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
|
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
|
||||||
hdlg, ds_optionsProc, (LPARAM) ci);
|
hdlg, ds_optionsProc, (LPARAM) ci);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,6 +341,7 @@ dconn_FDriverConnectProc(
|
|||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
|
dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
@ -393,6 +385,5 @@ dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free(our_connect_string);
|
free(our_connect_string);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* 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,
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* 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"
|
||||||
@ -54,6 +55,7 @@ SQLAllocEnv(HENV FAR *phenv)
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLFreeEnv(HENV henv)
|
SQLFreeEnv(HENV henv)
|
||||||
{
|
{
|
||||||
@ -73,8 +75,8 @@ SQLFreeEnv(HENV henv)
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the next SQL error information. */
|
|
||||||
|
|
||||||
|
/* Returns the next SQL error information. */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLError(
|
SQLError(
|
||||||
HENV henv,
|
HENV henv,
|
||||||
@ -208,24 +210,19 @@ SQLError(
|
|||||||
case STMT_INVALID_CURSOR_POSITION:
|
case STMT_INVALID_CURSOR_POSITION:
|
||||||
strcpy(szSqlState, "S1109");
|
strcpy(szSqlState, "S1109");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_VALUE_OUT_OF_RANGE:
|
case STMT_VALUE_OUT_OF_RANGE:
|
||||||
strcpy(szSqlState, "22003");
|
strcpy(szSqlState, "22003");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_OPERATION_INVALID:
|
case STMT_OPERATION_INVALID:
|
||||||
strcpy(szSqlState, "S1011");
|
strcpy(szSqlState, "S1011");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STMT_EXEC_ERROR:
|
case STMT_EXEC_ERROR:
|
||||||
default:
|
default:
|
||||||
strcpy(szSqlState, "S1000");
|
strcpy(szSqlState, "S1000");
|
||||||
/* also a general error */
|
/* also a general error */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
|
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -237,10 +234,11 @@ SQLError(
|
|||||||
szErrorMsg[0] = '\0';
|
szErrorMsg[0] = '\0';
|
||||||
|
|
||||||
mylog(" returning NO_DATA_FOUND\n");
|
mylog(" returning NO_DATA_FOUND\n");
|
||||||
|
|
||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
return SQL_SUCCESS;
|
|
||||||
|
|
||||||
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (SQL_NULL_HDBC != hdbc)
|
else if (SQL_NULL_HDBC != hdbc)
|
||||||
{
|
{
|
||||||
@ -310,7 +308,6 @@ SQLError(
|
|||||||
break;
|
break;
|
||||||
case CONN_TRANSACT_IN_PROGRES:
|
case CONN_TRANSACT_IN_PROGRES:
|
||||||
strcpy(szSqlState, "S1010");
|
strcpy(szSqlState, "S1010");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* when the user tries to switch commit mode in a
|
* when the user tries to switch commit mode in a
|
||||||
* transaction
|
* transaction
|
||||||
@ -324,18 +321,15 @@ SQLError(
|
|||||||
case STMT_NOT_IMPLEMENTED_ERROR:
|
case STMT_NOT_IMPLEMENTED_ERROR:
|
||||||
strcpy(szSqlState, "S1C00");
|
strcpy(szSqlState, "S1C00");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONN_VALUE_OUT_OF_RANGE:
|
case CONN_VALUE_OUT_OF_RANGE:
|
||||||
case STMT_VALUE_OUT_OF_RANGE:
|
case STMT_VALUE_OUT_OF_RANGE:
|
||||||
strcpy(szSqlState, "22003");
|
strcpy(szSqlState, "22003");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
strcpy(szSqlState, "S1000");
|
strcpy(szSqlState, "S1000");
|
||||||
/* general error */
|
/* general error */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -349,8 +343,8 @@ SQLError(
|
|||||||
|
|
||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
return SQL_SUCCESS;
|
|
||||||
|
|
||||||
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (SQL_NULL_HENV != henv)
|
else if (SQL_NULL_HENV != henv)
|
||||||
{
|
{
|
||||||
@ -419,15 +413,10 @@ SQLError(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
/*
|
/*
|
||||||
* EnvironmentClass implementation
|
* EnvironmentClass implementation
|
||||||
*/
|
*/
|
||||||
|
EnvironmentClass *
|
||||||
|
|
||||||
|
|
||||||
EnvironmentClass
|
|
||||||
*
|
|
||||||
EN_Constructor(void)
|
EN_Constructor(void)
|
||||||
{
|
{
|
||||||
EnvironmentClass *rv;
|
EnvironmentClass *rv;
|
||||||
@ -451,8 +440,10 @@ EN_Destructor(EnvironmentClass *self)
|
|||||||
|
|
||||||
mylog("in EN_Destructor, self=%u\n", self);
|
mylog("in EN_Destructor, self=%u\n", self);
|
||||||
|
|
||||||
/* the error messages are static strings distributed throughout */
|
/*
|
||||||
/* the source--they should not be freed */
|
* the error messages are static strings distributed throughout
|
||||||
|
* 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++)
|
||||||
@ -466,6 +457,7 @@ EN_Destructor(EnvironmentClass *self)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
EN_get_error(EnvironmentClass *self, int *number, char **message)
|
EN_get_error(EnvironmentClass *self, int *number, char **message)
|
||||||
{
|
{
|
||||||
@ -481,6 +473,7 @@ EN_get_error(EnvironmentClass *self, int *number, char **message)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
|
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
|
||||||
{
|
{
|
||||||
@ -504,6 +497,7 @@ EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
|
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
|
||||||
{
|
{
|
||||||
@ -519,6 +513,7 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EN_log_error(char *func, char *desc, EnvironmentClass *self)
|
EN_log_error(char *func, char *desc, EnvironmentClass *self)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: execute.c
|
/*-------
|
||||||
|
* Module: execute.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to
|
* Description: This module contains routines related to
|
||||||
* preparing and executing an SQL statement.
|
* preparing and executing an SQL statement.
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
|
* SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -126,14 +127,10 @@ SQLPrepare(HSTMT hstmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
|
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLExecDirect(
|
SQLExecDirect(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -155,8 +152,10 @@ SQLExecDirect(
|
|||||||
if (stmt->statement)
|
if (stmt->statement)
|
||||||
free(stmt->statement);
|
free(stmt->statement);
|
||||||
|
|
||||||
/* keep a copy of the un-parametrized statement, in case */
|
/*
|
||||||
/* they try to execute this statement again */
|
* keep a copy of the un-parametrized statement, in case
|
||||||
|
* they try to execute this statement again
|
||||||
|
*/
|
||||||
stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
|
stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
|
||||||
if (!stmt->statement)
|
if (!stmt->statement)
|
||||||
{
|
{
|
||||||
@ -170,9 +169,11 @@ SQLExecDirect(
|
|||||||
|
|
||||||
stmt->prepare = FALSE;
|
stmt->prepare = FALSE;
|
||||||
|
|
||||||
/* If an SQLPrepare was performed prior to this, but was left in */
|
/*
|
||||||
/* the premature state because an error occurred prior to SQLExecute */
|
* If an SQLPrepare was performed prior to this, but was left in
|
||||||
/* then set the statement to finished so it can be recycled. */
|
* the premature state because an error occurred prior to SQLExecute
|
||||||
|
* then set the statement to finished so it can be recycled.
|
||||||
|
*/
|
||||||
if (stmt->status == STMT_PREMATURE)
|
if (stmt->status == STMT_PREMATURE)
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
@ -195,6 +196,7 @@ SQLExecDirect(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Execute a prepared SQL statement */
|
/* Execute a prepared SQL statement */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLExecute(
|
SQLExecute(
|
||||||
@ -206,7 +208,6 @@ SQLExecute(
|
|||||||
int i,
|
int i,
|
||||||
retval;
|
retval;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
@ -280,7 +281,6 @@ SQLExecute(
|
|||||||
if ((stmt->prepare && stmt->status != STMT_READY) ||
|
if ((stmt->prepare && stmt->status != STMT_READY) ||
|
||||||
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
|
(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
|
||||||
{
|
{
|
||||||
|
|
||||||
stmt->errornumber = STMT_STATUS_ERROR;
|
stmt->errornumber = STMT_STATUS_ERROR;
|
||||||
stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
|
stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
|
||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
@ -288,7 +288,6 @@ SQLExecute(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
|
/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
|
||||||
if (!stmt->pre_executing)
|
if (!stmt->pre_executing)
|
||||||
{
|
{
|
||||||
@ -336,15 +335,10 @@ SQLExecute(
|
|||||||
|
|
||||||
mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params);
|
mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params);
|
||||||
|
|
||||||
|
|
||||||
return SC_execute(stmt);
|
return SC_execute(stmt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLTransact(
|
SQLTransact(
|
||||||
HENV henv,
|
HENV henv,
|
||||||
@ -380,7 +374,6 @@ SQLTransact(
|
|||||||
if (conn && conn->henv == henv)
|
if (conn && conn->henv == henv)
|
||||||
if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
|
if (SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
|
||||||
}
|
}
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -388,15 +381,9 @@ SQLTransact(
|
|||||||
conn = (ConnectionClass *) hdbc;
|
conn = (ConnectionClass *) hdbc;
|
||||||
|
|
||||||
if (fType == SQL_COMMIT)
|
if (fType == SQL_COMMIT)
|
||||||
{
|
|
||||||
stmt_string = "COMMIT";
|
stmt_string = "COMMIT";
|
||||||
|
|
||||||
}
|
|
||||||
else if (fType == SQL_ROLLBACK)
|
else if (fType == SQL_ROLLBACK)
|
||||||
{
|
|
||||||
stmt_string = "ROLLBACK";
|
stmt_string = "ROLLBACK";
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
|
conn->errornumber = CONN_INVALID_ARGUMENT_NO;
|
||||||
@ -408,7 +395,6 @@ SQLTransact(
|
|||||||
/* If manual commit and in transaction, then proceed. */
|
/* If manual commit and in transaction, then proceed. */
|
||||||
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string);
|
mylog("SQLTransact: sending on conn %d '%s'\n", conn, stmt_string);
|
||||||
|
|
||||||
res = CC_send_query(conn, stmt_string, NULL);
|
res = CC_send_query(conn, stmt_string, NULL);
|
||||||
@ -433,7 +419,6 @@ SQLTransact(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLCancel(
|
SQLCancel(
|
||||||
@ -464,8 +449,6 @@ SQLCancel(
|
|||||||
*/
|
*/
|
||||||
if (stmt->data_at_exec < 0)
|
if (stmt->data_at_exec < 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MAJOR HACK for Windows to reset the driver manager's cursor
|
* MAJOR HACK for Windows to reset the driver manager's cursor
|
||||||
* state: Because of what seems like a bug in the Odbc driver
|
* state: Because of what seems like a bug in the Odbc driver
|
||||||
@ -507,14 +490,14 @@ SQLCancel(
|
|||||||
stmt->put_data = FALSE;
|
stmt->put_data = FALSE;
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Returns the SQL string as modified by the driver. */
|
/*
|
||||||
/* Currently, just copy the input string without modification */
|
* Returns the SQL string as modified by the driver.
|
||||||
/* observing buffer limits and truncation. */
|
* Currently, just copy the input string without modification
|
||||||
|
* observing buffer limits and truncation.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLNativeSql(
|
SQLNativeSql(
|
||||||
HDBC hdbc,
|
HDBC hdbc,
|
||||||
@ -564,11 +547,11 @@ SQLNativeSql(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Supplies parameter data at execution time. Used in conjuction with */
|
|
||||||
/* SQLPutData. */
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supplies parameter data at execution time.
|
||||||
|
* Used in conjuction with SQLPutData.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLParamData(
|
SQLParamData(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -636,11 +619,9 @@ SQLParamData(
|
|||||||
|
|
||||||
CC_set_no_trans(stmt->hdbc);
|
CC_set_no_trans(stmt->hdbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt->lobj_fd = -1;
|
stmt->lobj_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Done, now copy the params and then execute the statement */
|
/* Done, now copy the params and then execute the statement */
|
||||||
if (stmt->data_at_exec == 0)
|
if (stmt->data_at_exec == 0)
|
||||||
{
|
{
|
||||||
@ -675,11 +656,11 @@ SQLParamData(
|
|||||||
return SQL_NEED_DATA;
|
return SQL_NEED_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* Supplies parameter data at execution time. Used in conjunction with */
|
|
||||||
/* SQLParamData. */
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supplies parameter data at execution time.
|
||||||
|
* Used in conjunction with SQLParamData.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLPutData(
|
SQLPutData(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -701,7 +682,6 @@ SQLPutData(
|
|||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (stmt->current_exec_param < 0)
|
if (stmt->current_exec_param < 0)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
@ -714,7 +694,6 @@ SQLPutData(
|
|||||||
|
|
||||||
if (!stmt->put_data)
|
if (!stmt->put_data)
|
||||||
{ /* first call */
|
{ /* first call */
|
||||||
|
|
||||||
mylog("SQLPutData: (1) cbValue = %d\n", cbValue);
|
mylog("SQLPutData: (1) cbValue = %d\n", cbValue);
|
||||||
|
|
||||||
stmt->put_data = TRUE;
|
stmt->put_data = TRUE;
|
||||||
@ -733,11 +712,9 @@ SQLPutData(
|
|||||||
if (cbValue == SQL_NULL_DATA)
|
if (cbValue == SQL_NULL_DATA)
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
/* Handle Long Var Binary with Large Objects */
|
/* Handle Long Var Binary with Large Objects */
|
||||||
if (current_param->SQLType == SQL_LONGVARBINARY)
|
if (current_param->SQLType == SQL_LONGVARBINARY)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* begin transaction if needed */
|
/* begin transaction if needed */
|
||||||
if (!CC_is_in_trans(stmt->hdbc))
|
if (!CC_is_in_trans(stmt->hdbc))
|
||||||
{
|
{
|
||||||
@ -775,8 +752,10 @@ SQLPutData(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* major hack -- to allow convert to see somethings there */
|
/*
|
||||||
/* have to modify convert to handle this better */
|
* major hack -- to allow convert to see somethings there
|
||||||
|
* have to modify convert to handle this better
|
||||||
|
*/
|
||||||
current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid;
|
current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid;
|
||||||
|
|
||||||
/* store the fd */
|
/* store the fd */
|
||||||
@ -791,11 +770,10 @@ SQLPutData(
|
|||||||
|
|
||||||
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
|
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
|
||||||
mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
|
mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* for handling fields */
|
{
|
||||||
|
/* for handling fields */
|
||||||
if (cbValue == SQL_NTS)
|
if (cbValue == SQL_NTS)
|
||||||
{
|
{
|
||||||
current_param->EXEC_buffer = strdup(rgbValue);
|
current_param->EXEC_buffer = strdup(rgbValue);
|
||||||
@ -841,25 +819,21 @@ SQLPutData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{ /* calling SQLPutData more than once */
|
{
|
||||||
|
/* calling SQLPutData more than once */
|
||||||
mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);
|
mylog("SQLPutData: (>1) cbValue = %d\n", cbValue);
|
||||||
|
|
||||||
if (current_param->SQLType == SQL_LONGVARBINARY)
|
if (current_param->SQLType == SQL_LONGVARBINARY)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* the large object fd is in EXEC_buffer */
|
/* the large object fd is in EXEC_buffer */
|
||||||
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
|
retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
|
||||||
mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
|
mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
|
||||||
|
|
||||||
*current_param->EXEC_used += cbValue;
|
*current_param->EXEC_used += cbValue;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
buffer = current_param->EXEC_buffer;
|
buffer = current_param->EXEC_buffer;
|
||||||
|
|
||||||
if (cbValue == SQL_NTS)
|
if (cbValue == SQL_NTS)
|
||||||
@ -880,11 +854,9 @@ SQLPutData(
|
|||||||
|
|
||||||
/* reassign buffer incase realloc moved it */
|
/* reassign buffer incase realloc moved it */
|
||||||
current_param->EXEC_buffer = buffer;
|
current_param->EXEC_buffer = buffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (cbValue > 0)
|
else if (cbValue > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
old_pos = *current_param->EXEC_used;
|
old_pos = *current_param->EXEC_used;
|
||||||
|
|
||||||
*current_param->EXEC_used += cbValue;
|
*current_param->EXEC_used += cbValue;
|
||||||
@ -906,17 +878,14 @@ SQLPutData(
|
|||||||
|
|
||||||
/* reassign buffer incase realloc moved it */
|
/* reassign buffer incase realloc moved it */
|
||||||
current_param->EXEC_buffer = buffer;
|
current_param->EXEC_buffer = buffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SC_log_error(func, "bad cbValue", stmt);
|
SC_log_error(func, "bad cbValue", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* GetPrivateProfileString()
|
/*-------
|
||||||
|
* GetPrivateProfileString()
|
||||||
*
|
*
|
||||||
* approximate implementation of
|
* approximate implementation of
|
||||||
* Windows NT System Services version of GetPrivateProfileString()
|
* Windows NT System Services version of GetPrivateProfileString()
|
||||||
@ -15,6 +16,7 @@
|
|||||||
* are allowed (that is an anachronism anyway)
|
* are allowed (that is an anachronism anyway)
|
||||||
* Added code to search for ODBC_INI file in users home directory on
|
* Added code to search for ODBC_INI file in users home directory on
|
||||||
* Unix
|
* Unix
|
||||||
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
@ -110,7 +112,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
|
aFile = (FILE *) (buf ? fopen(buf, PG_BINARY_R) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
|
aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
|
||||||
|
|
||||||
if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
|
if (theReturnBufferLength == 0 || theReturnBuffer == NULL)
|
||||||
@ -123,7 +124,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
if (aFile == NULL)
|
if (aFile == NULL)
|
||||||
{
|
{
|
||||||
/* no ini file specified, return the default */
|
/* no ini file specified, return the default */
|
||||||
|
|
||||||
++aLength; /* room for NULL char */
|
++aLength; /* room for NULL char */
|
||||||
aLength = theReturnBufferLength < aLength ?
|
aLength = theReturnBufferLength < aLength ?
|
||||||
theReturnBufferLength : aLength;
|
theReturnBufferLength : aLength;
|
||||||
@ -132,7 +132,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
return aLength - 1;
|
return aLength - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
|
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
|
||||||
{
|
{
|
||||||
aLineLength = strlen(aLine);
|
aLineLength = strlen(aLine);
|
||||||
@ -147,7 +146,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '[': /* section marker */
|
case '[': /* section marker */
|
||||||
|
|
||||||
if ((aString = strchr(aLine, ']')))
|
if ((aString = strchr(aLine, ']')))
|
||||||
{
|
{
|
||||||
aStart = aLine + 1;
|
aStart = aLine + 1;
|
||||||
@ -159,30 +157,25 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
*(aString + 1) = '\0';
|
*(aString + 1) = '\0';
|
||||||
|
|
||||||
/* accept as matched if NULL key or exact match */
|
/* accept as matched if NULL key or exact match */
|
||||||
|
|
||||||
if (!theSection || !strcmp(aStart, theSection))
|
if (!theSection || !strcmp(aStart, theSection))
|
||||||
aSectionFound = TRUE;
|
aSectionFound = TRUE;
|
||||||
else
|
else
|
||||||
aSectionFound = FALSE;
|
aSectionFound = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* try to match value keys if in proper section */
|
/* try to match value keys if in proper section */
|
||||||
|
|
||||||
if (aSectionFound)
|
if (aSectionFound)
|
||||||
{
|
{
|
||||||
/* try to match requested key */
|
/* try to match requested key */
|
||||||
|
|
||||||
if ((aString = aValue = strchr(aLine, '=')))
|
if ((aString = aValue = strchr(aLine, '=')))
|
||||||
{
|
{
|
||||||
*aValue = '\0';
|
*aValue = '\0';
|
||||||
++aValue;
|
++aValue;
|
||||||
|
|
||||||
/* strip leading blanks in value field */
|
/* strip leading blanks in value field */
|
||||||
|
|
||||||
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
|
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
|
||||||
*aValue++ = '\0';
|
*aValue++ = '\0';
|
||||||
if (aValue >= aLine + sizeof(aLine))
|
if (aValue >= aLine + sizeof(aLine))
|
||||||
@ -196,7 +189,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
aStart++;
|
aStart++;
|
||||||
|
|
||||||
/* strip trailing blanks from key */
|
/* strip trailing blanks from key */
|
||||||
|
|
||||||
if (aString)
|
if (aString)
|
||||||
{
|
{
|
||||||
while (--aString >= aStart && *aString == ' ')
|
while (--aString >= aStart && *aString == ' ')
|
||||||
@ -204,16 +196,13 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* see if key is matched */
|
/* see if key is matched */
|
||||||
|
|
||||||
if (theKey == NULL || !strcmp(theKey, aStart))
|
if (theKey == NULL || !strcmp(theKey, aStart))
|
||||||
{
|
{
|
||||||
/* matched -- first, terminate value part */
|
/* matched -- first, terminate value part */
|
||||||
|
|
||||||
aKeyFound = TRUE;
|
aKeyFound = TRUE;
|
||||||
aLength = strlen(aValue);
|
aLength = strlen(aValue);
|
||||||
|
|
||||||
/* remove trailing blanks from aValue if any */
|
/* remove trailing blanks from aValue if any */
|
||||||
|
|
||||||
aString = aValue + aLength - 1;
|
aString = aValue + aLength - 1;
|
||||||
|
|
||||||
while (--aString > aValue && *aString == ' ')
|
while (--aString > aValue && *aString == ' ')
|
||||||
@ -223,7 +212,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* unquote value if quoted */
|
/* unquote value if quoted */
|
||||||
|
|
||||||
if (aLength >= 2 && aValue[0] == '"' &&
|
if (aLength >= 2 && aValue[0] == '"' &&
|
||||||
aValue[aLength - 1] == '"')
|
aValue[aLength - 1] == '"')
|
||||||
{
|
{
|
||||||
@ -236,7 +224,6 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* single quotes allowed also... */
|
/* single quotes allowed also... */
|
||||||
|
|
||||||
if (aLength >= 2 && aValue[0] == '\'' &&
|
if (aLength >= 2 && aValue[0] == '\'' &&
|
||||||
aValue[aLength - 1] == '\'')
|
aValue[aLength - 1] == '\'')
|
||||||
{
|
{
|
||||||
@ -247,13 +234,11 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compute maximum length copyable */
|
/* compute maximum length copyable */
|
||||||
|
|
||||||
aLineLength = (aLength <
|
aLineLength = (aLength <
|
||||||
theReturnBufferLength - aReturnLength) ? aLength :
|
theReturnBufferLength - aReturnLength) ? aLength :
|
||||||
theReturnBufferLength - aReturnLength;
|
theReturnBufferLength - aReturnLength;
|
||||||
|
|
||||||
/* do the copy to return buffer */
|
/* do the copy to return buffer */
|
||||||
|
|
||||||
if (aLineLength)
|
if (aLineLength)
|
||||||
{
|
{
|
||||||
strncpy(&theReturnBuffer[aReturnLength],
|
strncpy(&theReturnBuffer[aReturnLength],
|
||||||
@ -270,11 +255,9 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
fclose(aFile);
|
fclose(aFile);
|
||||||
aFile = NULL;
|
aFile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,7 +266,8 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
fclose(aFile);
|
fclose(aFile);
|
||||||
|
|
||||||
if (!aKeyFound)
|
if (!aKeyFound)
|
||||||
{ /* key wasn't found return default */
|
{
|
||||||
|
/* key wasn't found return default */
|
||||||
++aLength; /* room for NULL char */
|
++aLength; /* room for NULL char */
|
||||||
aLength = theReturnBufferLength < aLength ?
|
aLength = theReturnBufferLength < aLength ?
|
||||||
theReturnBufferLength : aLength;
|
theReturnBufferLength : aLength;
|
||||||
@ -294,6 +278,7 @@ GetPrivateProfileString(char *theSection, /* section name */
|
|||||||
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
WritePrivateProfileString(char *theSection, /* section name */
|
WritePrivateProfileString(char *theSection, /* section name */
|
||||||
char *theKey, /* write key name */
|
char *theKey, /* write key name */
|
||||||
@ -304,8 +289,10 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Ok. What the hell's the default behaviour for a null input buffer, and null
|
/*
|
||||||
|
* Ok. What the hell's the default behaviour for a null input buffer, and null
|
||||||
* section name. For now if either are null I ignore the request, until
|
* section name. For now if either are null I ignore the request, until
|
||||||
* I find out different.
|
* I find out different.
|
||||||
*/
|
*/
|
||||||
@ -353,11 +340,12 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
if (ptr == NULL || *ptr == '\0')
|
if (ptr == NULL || *ptr == '\0')
|
||||||
ptr = "/home";
|
ptr = "/home";
|
||||||
|
|
||||||
/* This doesn't make it so we find an ini file but allows normal */
|
/*
|
||||||
/* processing to continue further on down. The likelihood is that */
|
* This doesn't make it so we find an ini file but allows normal
|
||||||
/* the file won't be found and thus the default value will be */
|
* processing to continue further on down. The likelihood is that
|
||||||
/* returned. */
|
* the file won't be found and thus the default value will be
|
||||||
/* */
|
* returned.
|
||||||
|
*/
|
||||||
if (MAXPGPATH - 1 < strlen(ptr) + j)
|
if (MAXPGPATH - 1 < strlen(ptr) + j)
|
||||||
{
|
{
|
||||||
if (MAXPGPATH - 1 < strlen(ptr))
|
if (MAXPGPATH - 1 < strlen(ptr))
|
||||||
@ -368,9 +356,10 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
|
|
||||||
sprintf(buf, "%s/%s", ptr, theIniFileName);
|
sprintf(buf, "%s/%s", ptr, theIniFileName);
|
||||||
|
|
||||||
/* This code makes it so that a file in the users home dir */
|
/*
|
||||||
/* overrides a the "default" file as passed in */
|
* This code makes it so that a file in the users home dir
|
||||||
/* */
|
* overrides a the "default" file as passed in
|
||||||
|
*/
|
||||||
aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
|
aFile = (FILE *) (buf ? fopen(buf, "r+") : NULL);
|
||||||
if (!aFile)
|
if (!aFile)
|
||||||
{
|
{
|
||||||
@ -380,13 +369,13 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
aLength = strlen(theBuffer);
|
aLength = strlen(theBuffer);
|
||||||
|
|
||||||
/* We have to search for theKey, because if it already */
|
/*
|
||||||
/* exists we have to overwrite it. If it doesn't exist */
|
* We have to search for theKey, because if it already
|
||||||
/* we just write a new line to the file. */
|
* exists we have to overwrite it. If it doesn't exist
|
||||||
/* */
|
* we just write a new line to the file.
|
||||||
|
*/
|
||||||
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
|
while (fgets(aLine, sizeof(aLine), aFile) != NULL)
|
||||||
{
|
{
|
||||||
aLineLength = strlen(aLine);
|
aLineLength = strlen(aLine);
|
||||||
@ -401,7 +390,6 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '[': /* section marker */
|
case '[': /* section marker */
|
||||||
|
|
||||||
if ((aString = strchr(aLine, ']')))
|
if ((aString = strchr(aLine, ']')))
|
||||||
{
|
{
|
||||||
*aString = '\0';
|
*aString = '\0';
|
||||||
@ -411,13 +399,10 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
if (!strcmp(aLine + 1, theSection))
|
if (!strcmp(aLine + 1, theSection))
|
||||||
aSectionFound = TRUE;
|
aSectionFound = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* try to match value keys if in proper section */
|
/* try to match value keys if in proper section */
|
||||||
|
|
||||||
if (aSectionFound)
|
if (aSectionFound)
|
||||||
{
|
{
|
||||||
/* try to match requested key */
|
/* try to match requested key */
|
||||||
@ -428,7 +413,6 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
++aValue;
|
++aValue;
|
||||||
|
|
||||||
/* strip leading blanks in value field */
|
/* strip leading blanks in value field */
|
||||||
|
|
||||||
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
|
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
|
||||||
*aValue++ = '\0';
|
*aValue++ = '\0';
|
||||||
if (aValue >= aLine + sizeof(aLine))
|
if (aValue >= aLine + sizeof(aLine))
|
||||||
@ -438,7 +422,6 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
aValue = "";
|
aValue = "";
|
||||||
|
|
||||||
/* strip trailing blanks from key */
|
/* strip trailing blanks from key */
|
||||||
|
|
||||||
if (aString)
|
if (aString)
|
||||||
{
|
{
|
||||||
while (--aString >= aLine && *aString == ' ')
|
while (--aString >= aLine && *aString == ' ')
|
||||||
@ -446,7 +429,6 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* see if key is matched */
|
/* see if key is matched */
|
||||||
|
|
||||||
if (!strcmp(theKey, aLine))
|
if (!strcmp(theKey, aLine))
|
||||||
{
|
{
|
||||||
keyFound = TRUE;
|
keyFound = TRUE;
|
||||||
@ -460,7 +442,6 @@ WritePrivateProfileString(char *theSection, /* section name */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: info.c
|
/*--------
|
||||||
|
* Module: info.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to
|
* Description: This module contains routines related to
|
||||||
* ODBC informational functions.
|
* ODBC informational functions.
|
||||||
@ -12,7 +13,7 @@
|
|||||||
* SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
|
* SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -56,8 +57,6 @@
|
|||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetInfo(
|
SQLGetInfo(
|
||||||
HDBC hdbc,
|
HDBC hdbc,
|
||||||
@ -154,7 +153,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
|
case SQL_CORRELATION_NAME: /* ODBC 1.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Saying no correlation name makes Query not work right.
|
* Saying no correlation name makes Query not work right.
|
||||||
* value = SQL_CN_NONE;
|
* value = SQL_CN_NONE;
|
||||||
@ -182,11 +180,10 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */
|
case SQL_DATABASE_NAME:/* Support for old ODBC 1.0 Apps */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returning the database name causes problems in MS Query. It
|
* Returning the database name causes problems in MS Query. It
|
||||||
* generates query like: "SELECT DISTINCT a FROM byronncrap3
|
* generates query like: "SELECT DISTINCT a FROM byronnbad3
|
||||||
* crap3"
|
* bad3"
|
||||||
*
|
*
|
||||||
* p = CC_get_database(conn);
|
* p = CC_get_database(conn);
|
||||||
*/
|
*/
|
||||||
@ -198,7 +195,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DBMS_VER: /* ODBC 1.0 */
|
case SQL_DBMS_VER: /* ODBC 1.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The ODBC spec wants ##.##.#### ...whatever... so prepend
|
* The ODBC spec wants ##.##.#### ...whatever... so prepend
|
||||||
* the driver
|
* the driver
|
||||||
@ -256,7 +252,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
|
case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* are identifiers case-sensitive (yes, but only when quoted.
|
* are identifiers case-sensitive (yes, but only when quoted.
|
||||||
* If not quoted, they default to lowercase)
|
* If not quoted, they default to lowercase)
|
||||||
@ -275,7 +270,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
|
case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is there a character that escapes '%' and '_' in a LIKE
|
* is there a character that escapes '%' and '_' in a LIKE
|
||||||
* clause? not as far as I can tell
|
* clause? not as far as I can tell
|
||||||
@ -356,18 +350,18 @@ SQLGetInfo(
|
|||||||
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
|
case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
|
||||||
len = 4;
|
len = 4;
|
||||||
if (PG_VERSION_GE(conn, 7.1))
|
if (PG_VERSION_GE(conn, 7.1))
|
||||||
{ /* Large Rowa in 7.1+ */
|
{
|
||||||
|
/* Large Rowa in 7.1+ */
|
||||||
value = MAX_ROW_SIZE;
|
value = MAX_ROW_SIZE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Without the Toaster we're limited to
|
{
|
||||||
* the blocksize */
|
/* Without the Toaster we're limited to the blocksize */
|
||||||
value = BLCKSZ;
|
value = BLCKSZ;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
|
case SQL_MAX_ROW_SIZE_INCLUDES_LONG: /* ODBC 2.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* does the preceding value include LONGVARCHAR and
|
* does the preceding value include LONGVARCHAR and
|
||||||
* LONGVARBINARY fields? Well, it does include longvarchar,
|
* LONGVARBINARY fields? Well, it does include longvarchar,
|
||||||
@ -379,12 +373,11 @@ SQLGetInfo(
|
|||||||
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
|
case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
|
||||||
/* maybe this should be 0? */
|
/* maybe this should be 0? */
|
||||||
len = 4;
|
len = 4;
|
||||||
|
/* Long Queries in 7.0+ */
|
||||||
if (PG_VERSION_GE(conn, 7.0))
|
if (PG_VERSION_GE(conn, 7.0))
|
||||||
{ /* Long Queries in 7.0+ */
|
|
||||||
value = MAX_STATEMENT_LEN;
|
value = MAX_STATEMENT_LEN;
|
||||||
}
|
/* Prior to 7.0 we used 2*BLCKSZ */
|
||||||
else if (PG_VERSION_GE(conn, 6.5)) /* Prior to 7.0 we used
|
else if (PG_VERSION_GE(conn, 6.5))
|
||||||
* 2*BLCKSZ */
|
|
||||||
value = (2 * BLCKSZ);
|
value = (2 * BLCKSZ);
|
||||||
else
|
else
|
||||||
/* Prior to 6.5 we used BLCKSZ */
|
/* Prior to 6.5 we used BLCKSZ */
|
||||||
@ -417,9 +410,8 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
|
case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dont need the length, SQLPutData can handle any size and
|
* Don't need the length, SQLPutData can handle any size and
|
||||||
* multiple calls
|
* multiple calls
|
||||||
*/
|
*/
|
||||||
p = "N";
|
p = "N";
|
||||||
@ -463,7 +455,8 @@ SQLGetInfo(
|
|||||||
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
|
case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
|
||||||
len = 4;
|
len = 4;
|
||||||
if (PG_VERSION_GE(conn, 7.1))
|
if (PG_VERSION_GE(conn, 7.1))
|
||||||
{ /* OJs in 7.1+ */
|
{
|
||||||
|
/* OJs in 7.1+ */
|
||||||
value = (SQL_OJ_LEFT |
|
value = (SQL_OJ_LEFT |
|
||||||
SQL_OJ_RIGHT |
|
SQL_OJ_RIGHT |
|
||||||
SQL_OJ_FULL |
|
SQL_OJ_FULL |
|
||||||
@ -473,9 +466,8 @@ SQLGetInfo(
|
|||||||
SQL_OJ_ALL_COMPARISON_OPS);
|
SQL_OJ_ALL_COMPARISON_OPS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* OJs not in <7.1 */
|
/* OJs not in <7.1 */
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
|
case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
|
||||||
@ -484,13 +476,11 @@ SQLGetInfo(
|
|||||||
|
|
||||||
case SQL_OUTER_JOINS: /* ODBC 1.0 */
|
case SQL_OUTER_JOINS: /* ODBC 1.0 */
|
||||||
if (PG_VERSION_GE(conn, 7.1))
|
if (PG_VERSION_GE(conn, 7.1))
|
||||||
{ /* OJs in 7.1+ */
|
/* OJs in 7.1+ */
|
||||||
p = "Y";
|
p = "Y";
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{ /* OJs not in <7.1 */
|
/* OJs not in <7.1 */
|
||||||
p = "N";
|
p = "N";
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_OWNER_TERM: /* ODBC 1.0 */
|
case SQL_OWNER_TERM: /* ODBC 1.0 */
|
||||||
@ -547,7 +537,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_ROW_UPDATES: /* ODBC 1.0 */
|
case SQL_ROW_UPDATES: /* ODBC 1.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Driver doesn't support keyset-driven or mixed cursors, so
|
* Driver doesn't support keyset-driven or mixed cursors, so
|
||||||
* not much point in saying row updates are supported
|
* not much point in saying row updates are supported
|
||||||
@ -635,7 +624,6 @@ SQLGetInfo(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
|
case SQL_TXN_CAPABLE: /* ODBC 1.0 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Postgres can deal with create or drop table statements in a
|
* Postgres can deal with create or drop table statements in a
|
||||||
* transaction
|
* transaction
|
||||||
@ -677,7 +665,8 @@ SQLGetInfo(
|
|||||||
* what length would be required if a real buffer had been passed in.
|
* what length would be required if a real buffer had been passed in.
|
||||||
*/
|
*/
|
||||||
if (p)
|
if (p)
|
||||||
{ /* char/binary data */
|
{
|
||||||
|
/* char/binary data */
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
|
|
||||||
if (rgbInfoValue)
|
if (rgbInfoValue)
|
||||||
@ -692,13 +681,11 @@ SQLGetInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{ /* numeric data */
|
{
|
||||||
|
/* numeric data */
|
||||||
if (rgbInfoValue)
|
if (rgbInfoValue)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (len == 2)
|
if (len == 2)
|
||||||
*((WORD *) rgbInfoValue) = (WORD) value;
|
*((WORD *) rgbInfoValue) = (WORD) value;
|
||||||
else if (len == 4)
|
else if (len == 4)
|
||||||
@ -712,8 +699,6 @@ SQLGetInfo(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetTypeInfo(
|
SQLGetTypeInfo(
|
||||||
@ -737,7 +722,6 @@ SQLGetTypeInfo(
|
|||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stmt->manual_result = TRUE;
|
stmt->manual_result = TRUE;
|
||||||
stmt->result = QR_Constructor();
|
stmt->result = QR_Constructor();
|
||||||
if (!stmt->result)
|
if (!stmt->result)
|
||||||
@ -801,7 +785,6 @@ SQLGetTypeInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
stmt->currTuple = -1;
|
stmt->currTuple = -1;
|
||||||
stmt->rowset_start = -1;
|
stmt->rowset_start = -1;
|
||||||
@ -810,7 +793,6 @@ SQLGetTypeInfo(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetFunctions(
|
SQLGetFunctions(
|
||||||
@ -824,7 +806,6 @@ SQLGetFunctions(
|
|||||||
|
|
||||||
if (fFunction == SQL_API_ALL_FUNCTIONS)
|
if (fFunction == SQL_API_ALL_FUNCTIONS)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (globals.lie)
|
if (globals.lie)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -910,13 +891,10 @@ SQLGetFunctions(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
if (globals.lie)
|
if (globals.lie)
|
||||||
*pfExists = TRUE;
|
*pfExists = TRUE;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (fFunction)
|
switch (fFunction)
|
||||||
{
|
{
|
||||||
case SQL_API_SQLALLOCCONNECT:
|
case SQL_API_SQLALLOCCONNECT:
|
||||||
@ -1094,12 +1072,10 @@ SQLGetFunctions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLTables(
|
SQLTables(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1161,13 +1137,12 @@ SQLTables(
|
|||||||
}
|
}
|
||||||
tbl_stmt = (StatementClass *) htbl_stmt;
|
tbl_stmt = (StatementClass *) htbl_stmt;
|
||||||
|
|
||||||
/* ********************************************************************** */
|
/*
|
||||||
/* Create the query to find out the tables */
|
* Create the query to find out the tables
|
||||||
/* ********************************************************************** */
|
*/
|
||||||
|
|
||||||
if (PG_VERSION_GE(conn, 7.1))
|
if (PG_VERSION_GE(conn, 7.1))
|
||||||
{ /* view is represented by its relkind
|
{
|
||||||
* since 7.1 */
|
/* view is represented by its relkind since 7.1 */
|
||||||
strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
|
strcpy(tables_query, "select relname, usename, relkind from pg_class, pg_user");
|
||||||
strcat(tables_query, " where relkind in ('r', 'v')");
|
strcat(tables_query, " where relkind in ('r', 'v')");
|
||||||
}
|
}
|
||||||
@ -1180,15 +1155,12 @@ SQLTables(
|
|||||||
my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
|
my_strcat(tables_query, " and usename like '%.*s'", szTableOwner, cbTableOwner);
|
||||||
my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
|
my_strcat(tables_query, " and relname like '%.*s'", szTableName, cbTableName);
|
||||||
|
|
||||||
|
|
||||||
/* Parse the extra systable prefix */
|
/* Parse the extra systable prefix */
|
||||||
strcpy(prefixes, globals.extra_systable_prefixes);
|
strcpy(prefixes, globals.extra_systable_prefixes);
|
||||||
i = 0;
|
i = 0;
|
||||||
prefix[i] = strtok(prefixes, ";");
|
prefix[i] = strtok(prefixes, ";");
|
||||||
while (prefix[i] && i < 32)
|
while (prefix[i] && i < 32)
|
||||||
{
|
|
||||||
prefix[++i] = strtok(NULL, ";");
|
prefix[++i] = strtok(NULL, ";");
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse the desired table types to return */
|
/* Parse the desired table types to return */
|
||||||
show_system_tables = FALSE;
|
show_system_tables = FALSE;
|
||||||
@ -1216,7 +1188,6 @@ SQLTables(
|
|||||||
show_regular_tables = TRUE;
|
show_regular_tables = TRUE;
|
||||||
else if (strstr(table_type[i], "VIEW"))
|
else if (strstr(table_type[i], "VIEW"))
|
||||||
show_views = TRUE;
|
show_views = TRUE;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1243,21 +1214,17 @@ SQLTables(
|
|||||||
strcat(tables_query, prefix[i]);
|
strcat(tables_query, prefix[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(tables_query, "'");
|
strcat(tables_query, "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* match users */
|
/* match users */
|
||||||
if (PG_VERSION_LT(conn, 7.1)) /* filter out large objects in
|
if (PG_VERSION_LT(conn, 7.1))
|
||||||
* older versions */
|
/* filter out large objects in older versions */
|
||||||
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
|
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
|
||||||
|
|
||||||
strcat(tables_query, " and usesysid = relowner");
|
strcat(tables_query, " and usesysid = relowner");
|
||||||
strcat(tables_query, " order by relname");
|
strcat(tables_query, " order by relname");
|
||||||
|
|
||||||
/* ********************************************************************** */
|
|
||||||
|
|
||||||
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
|
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
@ -1330,7 +1297,6 @@ SQLTables(
|
|||||||
result = SQLFetch(htbl_stmt);
|
result = SQLFetch(htbl_stmt);
|
||||||
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if this table name is a system table. If treating
|
* Determine if this table name is a system table. If treating
|
||||||
* system tables as regular tables, then no need to do this test.
|
* system tables as regular tables, then no need to do this test.
|
||||||
@ -1338,12 +1304,12 @@ SQLTables(
|
|||||||
systable = FALSE;
|
systable = FALSE;
|
||||||
if (!atoi(ci->show_system_tables))
|
if (!atoi(ci->show_system_tables))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
|
if (strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0)
|
||||||
systable = TRUE;
|
systable = TRUE;
|
||||||
|
|
||||||
else
|
else
|
||||||
{ /* Check extra system table prefixes */
|
{
|
||||||
|
/* Check extra system table prefixes */
|
||||||
i = 0;
|
i = 0;
|
||||||
while (prefix[i])
|
while (prefix[i])
|
||||||
{
|
{
|
||||||
@ -1359,8 +1325,8 @@ SQLTables(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if the table name is a view */
|
/* Determine if the table name is a view */
|
||||||
if (PG_VERSION_GE(conn, 7.1)) /* view is represented by its
|
if (PG_VERSION_GE(conn, 7.1))
|
||||||
* relkind since 7.1 */
|
/* view is represented by its relkind since 7.1 */
|
||||||
view = (relkind_or_hasrules[0] == 'v');
|
view = (relkind_or_hasrules[0] == 'v');
|
||||||
else
|
else
|
||||||
view = (relkind_or_hasrules[0] == '1');
|
view = (relkind_or_hasrules[0] == '1');
|
||||||
@ -1379,16 +1345,18 @@ SQLTables(
|
|||||||
(view && show_views) ||
|
(view && show_views) ||
|
||||||
(regular_table && show_regular_tables))
|
(regular_table && show_regular_tables))
|
||||||
{
|
{
|
||||||
|
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
|
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
|
||||||
|
|
||||||
set_tuplefield_string(&row->tuple[0], "");
|
set_tuplefield_string(&row->tuple[0], "");
|
||||||
|
|
||||||
/* I have to hide the table owner from Access, otherwise it */
|
/*
|
||||||
/* insists on referring to the table as 'owner.table'. */
|
* I have to hide the table owner from Access, otherwise it
|
||||||
/* (this is valid according to the ODBC SQL grammar, but */
|
* insists on referring to the table as 'owner.table'.
|
||||||
/* Postgres won't support it.) */
|
* (this is valid according to the ODBC SQL grammar, but
|
||||||
/* set_tuplefield_string(&row->tuple[1], table_owner); */
|
* Postgres won't support it.)
|
||||||
|
*
|
||||||
|
* set_tuplefield_string(&row->tuple[1], table_owner);
|
||||||
|
*/
|
||||||
|
|
||||||
mylog("SQLTables: table_name = '%s'\n", table_name);
|
mylog("SQLTables: table_name = '%s'\n", table_name);
|
||||||
|
|
||||||
@ -1410,8 +1378,10 @@ SQLTables(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* also, things need to think that this statement is finished so */
|
/*
|
||||||
/* the results can be retrieved. */
|
* also, things need to think that this statement is finished so
|
||||||
|
* the results can be retrieved.
|
||||||
|
*/
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
/* set up the current tuple pointer for SQLFetch */
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
@ -1425,8 +1395,6 @@ SQLTables(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLColumns(
|
SQLColumns(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1479,13 +1447,10 @@ SQLColumns(
|
|||||||
conn = (ConnectionClass *) (stmt->hdbc);
|
conn = (ConnectionClass *) (stmt->hdbc);
|
||||||
ci = &stmt->hdbc->connInfo;
|
ci = &stmt->hdbc->connInfo;
|
||||||
|
|
||||||
/* ********************************************************************** */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the query to find out the columns (Note: pre 6.3 did not
|
* Create the query to find out the columns (Note: pre 6.3 did not
|
||||||
* have the atttypmod field)
|
* have the atttypmod field)
|
||||||
*/
|
*/
|
||||||
/* ********************************************************************** */
|
|
||||||
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
|
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
|
||||||
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
|
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
|
||||||
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
|
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
|
||||||
@ -1497,10 +1462,11 @@ SQLColumns(
|
|||||||
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
|
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
|
||||||
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
|
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
|
||||||
|
|
||||||
/* give the output in the order the columns were defined */
|
/*
|
||||||
/* when the table was created */
|
* give the output in the order the columns were defined
|
||||||
|
* when the table was created
|
||||||
|
*/
|
||||||
strcat(columns_query, " order by attnum");
|
strcat(columns_query, " order by attnum");
|
||||||
/* ********************************************************************** */
|
|
||||||
|
|
||||||
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
@ -1673,10 +1639,8 @@ SQLColumns(
|
|||||||
QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
|
QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
|
||||||
QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
|
QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
|
||||||
|
|
||||||
|
|
||||||
result = SQLFetch(hcol_stmt);
|
result = SQLFetch(hcol_stmt);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only show oid if option AND there are other columns AND it's not
|
* Only show oid if option AND there are other columns AND it's not
|
||||||
* being called by SQLStatistics . Always show OID if it's a system
|
* being called by SQLStatistics . Always show OID if it's a system
|
||||||
@ -1685,12 +1649,10 @@ SQLColumns(
|
|||||||
|
|
||||||
if (result != SQL_ERROR && !stmt->internal)
|
if (result != SQL_ERROR && !stmt->internal)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (relhasrules[0] != '1' &&
|
if (relhasrules[0] != '1' &&
|
||||||
(atoi(ci->show_oid_column) ||
|
(atoi(ci->show_oid_column) ||
|
||||||
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
|
strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* For OID fields */
|
/* For OID fields */
|
||||||
the_type = PG_TYPE_OID;
|
the_type = PG_TYPE_OID;
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) +
|
row = (TupleNode *) malloc(sizeof(TupleNode) +
|
||||||
@ -1718,7 +1680,6 @@ SQLColumns(
|
|||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
QR_add_tuple(stmt->result, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
||||||
@ -1776,11 +1737,9 @@ SQLColumns(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((field_type == PG_TYPE_VARCHAR) ||
|
if ((field_type == PG_TYPE_VARCHAR) ||
|
||||||
(field_type == PG_TYPE_BPCHAR))
|
(field_type == PG_TYPE_BPCHAR))
|
||||||
{
|
{
|
||||||
|
|
||||||
useStaticPrecision = FALSE;
|
useStaticPrecision = FALSE;
|
||||||
|
|
||||||
if (mod_length >= 4)
|
if (mod_length >= 4)
|
||||||
@ -1827,8 +1786,10 @@ SQLColumns(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the row version column at the end so it might not be */
|
/*
|
||||||
/* mistaken for a key field. */
|
* Put the row version column at the end so it might not be
|
||||||
|
* mistaken for a key field.
|
||||||
|
*/
|
||||||
if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
|
if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
|
||||||
{
|
{
|
||||||
/* For Row Versioning fields */
|
/* For Row Versioning fields */
|
||||||
@ -1855,8 +1816,10 @@ SQLColumns(
|
|||||||
QR_add_tuple(stmt->result, row);
|
QR_add_tuple(stmt->result, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* also, things need to think that this statement is finished so */
|
/*
|
||||||
/* the results can be retrieved. */
|
* also, things need to think that this statement is finished so
|
||||||
|
* the results can be retrieved.
|
||||||
|
*/
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
/* set up the current tuple pointer for SQLFetch */
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
@ -1869,6 +1832,7 @@ SQLColumns(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSpecialColumns(
|
SQLSpecialColumns(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1892,8 +1856,6 @@ SQLSpecialColumns(
|
|||||||
RETCODE result;
|
RETCODE result;
|
||||||
char relhasrules[MAX_INFO_STRING];
|
char relhasrules[MAX_INFO_STRING];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...stmt=%u\n", func, stmt);
|
mylog("%s: entering...stmt=%u\n", func, stmt);
|
||||||
|
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
@ -1905,10 +1867,9 @@ SQLSpecialColumns(
|
|||||||
|
|
||||||
stmt->manual_result = TRUE;
|
stmt->manual_result = TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
/* ********************************************************************** */
|
* Create the query to find out if this is a view or not...
|
||||||
/* Create the query to find out if this is a view or not... */
|
*/
|
||||||
/* ********************************************************************** */
|
|
||||||
sprintf(columns_query, "select c.relhasrules "
|
sprintf(columns_query, "select c.relhasrules "
|
||||||
"from pg_user u, pg_class c where "
|
"from pg_user u, pg_class c where "
|
||||||
"u.usesysid = c.relowner");
|
"u.usesysid = c.relowner");
|
||||||
@ -1988,7 +1949,6 @@ SQLSpecialColumns(
|
|||||||
}
|
}
|
||||||
else if (fColType == SQL_ROWVER)
|
else if (fColType == SQL_ROWVER)
|
||||||
{
|
{
|
||||||
|
|
||||||
Int2 the_type = PG_TYPE_INT4;
|
Int2 the_type = PG_TYPE_INT4;
|
||||||
|
|
||||||
if (atoi(ci->row_versioning))
|
if (atoi(ci->row_versioning))
|
||||||
@ -2009,8 +1969,6 @@ SQLSpecialColumns(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
stmt->currTuple = -1;
|
stmt->currTuple = -1;
|
||||||
stmt->rowset_start = -1;
|
stmt->rowset_start = -1;
|
||||||
@ -2020,6 +1978,7 @@ SQLSpecialColumns(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLStatistics(
|
SQLStatistics(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -2104,9 +2063,10 @@ SQLStatistics(
|
|||||||
QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
|
QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
|
||||||
QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
|
QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
|
||||||
|
/*
|
||||||
/* only use the table name... the owner should be redundant, and */
|
* only use the table name... the owner should be redundant, and
|
||||||
/* we never use qualifiers. */
|
* we never use qualifiers.
|
||||||
|
*/
|
||||||
table_name = make_string(szTableName, cbTableName, NULL);
|
table_name = make_string(szTableName, cbTableName, NULL);
|
||||||
if (!table_name)
|
if (!table_name)
|
||||||
{
|
{
|
||||||
@ -2116,8 +2076,10 @@ SQLStatistics(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need to get a list of the field names first, */
|
/*
|
||||||
/* so we can return them later. */
|
* we need to get a list of the field names first,
|
||||||
|
* so we can return them later.
|
||||||
|
*/
|
||||||
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
@ -2172,6 +2134,7 @@ SQLStatistics(
|
|||||||
|
|
||||||
result = SQLFetch(hcol_stmt);
|
result = SQLFetch(hcol_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != SQL_NO_DATA_FOUND || total_columns == 0)
|
if (result != SQL_NO_DATA_FOUND || total_columns == 0)
|
||||||
{
|
{
|
||||||
stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
|
stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
|
||||||
@ -2205,14 +2168,15 @@ SQLStatistics(
|
|||||||
result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
|
result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
|
||||||
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "Couldn't execute
|
/*
|
||||||
* index query
|
* "Couldn't execute index query (w/SQLExecDirect) in
|
||||||
* (w/SQLExecDirect) in
|
* SQLStatistics.";
|
||||||
* SQLStatistics."; */
|
*/
|
||||||
|
stmt->errormsg = SC_create_errormsg(hindx_stmt);
|
||||||
|
|
||||||
stmt->errornumber = indx_stmt->errornumber;
|
stmt->errornumber = indx_stmt->errornumber;
|
||||||
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
||||||
goto SEEYA;
|
goto SEEYA;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bind the index name column */
|
/* bind the index name column */
|
||||||
@ -2314,7 +2278,6 @@ SQLStatistics(
|
|||||||
result = SQLFetch(hindx_stmt);
|
result = SQLFetch(hindx_stmt);
|
||||||
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* If only requesting unique indexs, then just return those. */
|
/* If only requesting unique indexs, then just return those. */
|
||||||
if (fUnique == SQL_INDEX_ALL ||
|
if (fUnique == SQL_INDEX_ALL ||
|
||||||
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
|
(fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
|
||||||
@ -2323,7 +2286,6 @@ SQLStatistics(
|
|||||||
/* add a row in this table for each field in the index */
|
/* add a row in this table for each field in the index */
|
||||||
while (i < 16 && fields_vector[i] != 0)
|
while (i < 16 && fields_vector[i] != 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) +
|
row = (TupleNode *) malloc(sizeof(TupleNode) +
|
||||||
(13 - 1) *sizeof(TupleField));
|
(13 - 1) *sizeof(TupleField));
|
||||||
|
|
||||||
@ -2380,8 +2342,8 @@ SQLStatistics(
|
|||||||
}
|
}
|
||||||
if (result != SQL_NO_DATA_FOUND)
|
if (result != SQL_NO_DATA_FOUND)
|
||||||
{
|
{
|
||||||
stmt->errormsg = SC_create_errormsg(hindx_stmt); /* "SQLFetch failed in
|
/* "SQLFetch failed in SQLStatistics."; */
|
||||||
* SQLStatistics."; */
|
stmt->errormsg = SC_create_errormsg(hindx_stmt);
|
||||||
stmt->errornumber = indx_stmt->errornumber;
|
stmt->errornumber = indx_stmt->errornumber;
|
||||||
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
||||||
goto SEEYA;
|
goto SEEYA;
|
||||||
@ -2389,8 +2351,10 @@ SQLStatistics(
|
|||||||
|
|
||||||
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
SQLFreeStmt(hindx_stmt, SQL_DROP);
|
||||||
|
|
||||||
/* also, things need to think that this statement is finished so */
|
/*
|
||||||
/* the results can be retrieved. */
|
* also, things need to think that this statement is finished so
|
||||||
|
* the results can be retrieved.
|
||||||
|
*/
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
/* set up the current tuple pointer for SQLFetch */
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
@ -2418,6 +2382,7 @@ SEEYA:
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLColumnPrivileges(
|
SQLColumnPrivileges(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -2441,7 +2406,9 @@ SQLColumnPrivileges(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SQLPrimaryKeys()
|
/*
|
||||||
|
* SQLPrimaryKeys()
|
||||||
|
*
|
||||||
* Retrieve the primary key columns for the specified table.
|
* Retrieve the primary key columns for the specified table.
|
||||||
*/
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
@ -2572,7 +2539,6 @@ SQLPrimaryKeys(
|
|||||||
|
|
||||||
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
|
||||||
{
|
{
|
||||||
|
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
||||||
|
|
||||||
set_tuplefield_null(&row->tuple[0]);
|
set_tuplefield_null(&row->tuple[0]);
|
||||||
@ -2608,8 +2574,10 @@ SQLPrimaryKeys(
|
|||||||
SQLFreeStmt(htbl_stmt, SQL_DROP);
|
SQLFreeStmt(htbl_stmt, SQL_DROP);
|
||||||
|
|
||||||
|
|
||||||
/* also, things need to think that this statement is finished so */
|
/*
|
||||||
/* the results can be retrieved. */
|
* also, things need to think that this statement is finished so
|
||||||
|
* the results can be retrieved.
|
||||||
|
*/
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
/* set up the current tuple pointer for SQLFetch */
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
@ -2621,6 +2589,7 @@ SQLPrimaryKeys(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLForeignKeys(
|
SQLForeignKeys(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -2667,15 +2636,12 @@ SQLForeignKeys(
|
|||||||
|
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
SWORD defer_type;
|
SWORD defer_type;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
char pkey[MAX_INFO_STRING];
|
char pkey[MAX_INFO_STRING];
|
||||||
Int2 result_cols;
|
Int2 result_cols;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...stmt=%u\n", func, stmt);
|
mylog("%s: entering...stmt=%u\n", func, stmt);
|
||||||
|
|
||||||
|
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
{
|
{
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -2723,8 +2689,10 @@ SQLForeignKeys(
|
|||||||
QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
|
QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
|
||||||
#endif /* ODBCVER >= 0x0300 */
|
#endif /* ODBCVER >= 0x0300 */
|
||||||
|
|
||||||
/* also, things need to think that this statement is finished so */
|
/*
|
||||||
/* the results can be retrieved. */
|
* also, things need to think that this statement is finished so
|
||||||
|
* the results can be retrieved.
|
||||||
|
*/
|
||||||
stmt->status = STMT_FINISHED;
|
stmt->status = STMT_FINISHED;
|
||||||
|
|
||||||
/* set up the current tuple pointer for SQLFetch */
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
@ -2898,7 +2866,6 @@ SQLForeignKeys(
|
|||||||
|
|
||||||
while (result == SQL_SUCCESS)
|
while (result == SQL_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Compute the number of keyparts. */
|
/* Compute the number of keyparts. */
|
||||||
num_keys = (trig_nargs - 4) / 2;
|
num_keys = (trig_nargs - 4) / 2;
|
||||||
|
|
||||||
@ -2913,7 +2880,6 @@ SQLForeignKeys(
|
|||||||
/* If there is a pk table specified, then check it. */
|
/* If there is a pk table specified, then check it. */
|
||||||
if (pk_table_needed[0] != '\0')
|
if (pk_table_needed[0] != '\0')
|
||||||
{
|
{
|
||||||
|
|
||||||
/* If it doesn't match, then continue */
|
/* If it doesn't match, then continue */
|
||||||
if (strcmp(pk_table, pk_table_needed))
|
if (strcmp(pk_table, pk_table_needed))
|
||||||
{
|
{
|
||||||
@ -2932,7 +2898,6 @@ SQLForeignKeys(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check that the key listed is the primary key */
|
/* Check that the key listed is the primary key */
|
||||||
keyresult = SQLFetch(hpkey_stmt);
|
keyresult = SQLFetch(hpkey_stmt);
|
||||||
|
|
||||||
@ -2949,7 +2914,6 @@ SQLForeignKeys(
|
|||||||
num_keys = 0;
|
num_keys = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get to next primary key */
|
/* Get to next primary key */
|
||||||
for (k = 0; k < 2; k++)
|
for (k = 0; k < 2; k++)
|
||||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||||
@ -3002,7 +2966,6 @@ SQLForeignKeys(
|
|||||||
|
|
||||||
for (k = 0; k < num_keys; k++)
|
for (k = 0; k < num_keys; k++)
|
||||||
{
|
{
|
||||||
|
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
||||||
|
|
||||||
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
|
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
|
||||||
@ -3050,7 +3013,6 @@ SQLForeignKeys(
|
|||||||
*/
|
*/
|
||||||
else if (pk_table_needed[0] != '\0')
|
else if (pk_table_needed[0] != '\0')
|
||||||
{
|
{
|
||||||
|
|
||||||
sprintf(tables_query, "SELECT pg_trigger.tgargs, "
|
sprintf(tables_query, "SELECT pg_trigger.tgargs, "
|
||||||
" pg_trigger.tgnargs, "
|
" pg_trigger.tgnargs, "
|
||||||
" pg_trigger.tgdeferrable, "
|
" pg_trigger.tgdeferrable, "
|
||||||
@ -3172,7 +3134,6 @@ SQLForeignKeys(
|
|||||||
|
|
||||||
while (result == SQL_SUCCESS)
|
while (result == SQL_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Calculate the number of key parts */
|
/* Calculate the number of key parts */
|
||||||
num_keys = (trig_nargs - 4) / 2;;
|
num_keys = (trig_nargs - 4) / 2;;
|
||||||
|
|
||||||
@ -3216,7 +3177,6 @@ SQLForeignKeys(
|
|||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||||
|
|
||||||
|
|
||||||
/* Get to first foreign table */
|
/* Get to first foreign table */
|
||||||
fk_table = trig_args;
|
fk_table = trig_args;
|
||||||
fk_table += strlen(fk_table) + 1;
|
fk_table += strlen(fk_table) + 1;
|
||||||
@ -3228,7 +3188,6 @@ SQLForeignKeys(
|
|||||||
|
|
||||||
for (k = 0; k < num_keys; k++)
|
for (k = 0; k < num_keys; k++)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
|
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
|
||||||
|
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
||||||
@ -3270,7 +3229,6 @@ SQLForeignKeys(
|
|||||||
fkey_ptr += strlen(fkey_ptr) + 1;
|
fkey_ptr += strlen(fkey_ptr) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SQLFetch(htbl_stmt);
|
result = SQLFetch(htbl_stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3290,7 +3248,6 @@ SQLForeignKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLProcedureColumns(
|
SQLProcedureColumns(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -3311,6 +3268,7 @@ SQLProcedureColumns(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLProcedures(
|
SQLProcedures(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -3329,6 +3287,7 @@ SQLProcedures(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLTablePrivileges(
|
SQLTablePrivileges(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: lobj.c
|
/*--------
|
||||||
|
* Module: lobj.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to manipulating
|
* Description: This module contains routines related to manipulating
|
||||||
* large objects.
|
* large objects.
|
||||||
@ -8,13 +9,14 @@
|
|||||||
* 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 "lobj.h"
|
#include "lobj.h"
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
|
||||||
Oid
|
Oid
|
||||||
lo_creat(ConnectionClass *conn, int mode)
|
lo_creat(ConnectionClass *conn, int mode)
|
||||||
{
|
{
|
||||||
@ -30,10 +32,9 @@ lo_creat(ConnectionClass *conn, int mode)
|
|||||||
return 0; /* invalid oid */
|
return 0; /* invalid oid */
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_open(ConnectionClass *conn, int lobjId, int mode)
|
lo_open(ConnectionClass *conn, int lobjId, int mode)
|
||||||
{
|
{
|
||||||
@ -41,7 +42,6 @@ lo_open(ConnectionClass *conn, int lobjId, int mode)
|
|||||||
int result_len;
|
int result_len;
|
||||||
LO_ARG argv[2];
|
LO_ARG argv[2];
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = lobjId;
|
argv[0].u.integer = lobjId;
|
||||||
@ -59,6 +59,7 @@ lo_open(ConnectionClass *conn, int lobjId, int mode)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_close(ConnectionClass *conn, int fd)
|
lo_close(ConnectionClass *conn, int fd)
|
||||||
{
|
{
|
||||||
@ -66,17 +67,14 @@ lo_close(ConnectionClass *conn, int fd)
|
|||||||
int retval,
|
int retval,
|
||||||
result_len;
|
result_len;
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = fd;
|
argv[0].u.integer = fd;
|
||||||
|
|
||||||
if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
|
if (!CC_send_function(conn, LO_CLOSE, &retval, &result_len, 1, argv, 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -86,7 +84,6 @@ lo_read(ConnectionClass *conn, int fd, char *buf, int len)
|
|||||||
LO_ARG argv[2];
|
LO_ARG argv[2];
|
||||||
int result_len;
|
int result_len;
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = fd;
|
argv[0].u.integer = fd;
|
||||||
@ -97,11 +94,11 @@ lo_read(ConnectionClass *conn, int fd, char *buf, int len)
|
|||||||
|
|
||||||
if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
|
if (!CC_send_function(conn, LO_READ, (int *) buf, &result_len, 0, argv, 2))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return result_len;
|
return result_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_write(ConnectionClass *conn, int fd, char *buf, int len)
|
lo_write(ConnectionClass *conn, int fd, char *buf, int len)
|
||||||
{
|
{
|
||||||
@ -109,7 +106,6 @@ lo_write(ConnectionClass *conn, int fd, char *buf, int len)
|
|||||||
int retval,
|
int retval,
|
||||||
result_len;
|
result_len;
|
||||||
|
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -123,11 +119,11 @@ lo_write(ConnectionClass *conn, int fd, char *buf, int len)
|
|||||||
|
|
||||||
if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
|
if (!CC_send_function(conn, LO_WRITE, &retval, &result_len, 1, argv, 2))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
|
lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
|
||||||
{
|
{
|
||||||
@ -135,7 +131,6 @@ lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
|
|||||||
int retval,
|
int retval,
|
||||||
result_len;
|
result_len;
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = fd;
|
argv[0].u.integer = fd;
|
||||||
@ -150,11 +145,11 @@ lo_lseek(ConnectionClass *conn, int fd, int offset, int whence)
|
|||||||
|
|
||||||
if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
|
if (!CC_send_function(conn, LO_LSEEK, &retval, &result_len, 1, argv, 3))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_tell(ConnectionClass *conn, int fd)
|
lo_tell(ConnectionClass *conn, int fd)
|
||||||
{
|
{
|
||||||
@ -162,18 +157,17 @@ lo_tell(ConnectionClass *conn, int fd)
|
|||||||
int retval,
|
int retval,
|
||||||
result_len;
|
result_len;
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = fd;
|
argv[0].u.integer = fd;
|
||||||
|
|
||||||
if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
|
if (!CC_send_function(conn, LO_TELL, &retval, &result_len, 1, argv, 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lo_unlink(ConnectionClass *conn, Oid lobjId)
|
lo_unlink(ConnectionClass *conn, Oid lobjId)
|
||||||
{
|
{
|
||||||
@ -181,14 +175,12 @@ lo_unlink(ConnectionClass *conn, Oid lobjId)
|
|||||||
int retval,
|
int retval,
|
||||||
result_len;
|
result_len;
|
||||||
|
|
||||||
|
|
||||||
argv[0].isint = 1;
|
argv[0].isint = 1;
|
||||||
argv[0].len = 4;
|
argv[0].len = 4;
|
||||||
argv[0].u.integer = lobjId;
|
argv[0].u.integer = lobjId;
|
||||||
|
|
||||||
if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
|
if (!CC_send_function(conn, LO_UNLINK, &retval, &result_len, 1, argv, 1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* 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.
|
||||||
@ -8,7 +9,7 @@
|
|||||||
* 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>
|
||||||
@ -31,6 +32,7 @@
|
|||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
void generate_filename(char *, char *, char *);
|
void generate_filename(char *, char *, char *);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
generate_filename(char *dirname, char *prefix, char *filename)
|
generate_filename(char *dirname, char *prefix, char *filename)
|
||||||
{
|
{
|
||||||
@ -56,8 +58,8 @@ generate_filename(char *dirname, char *prefix, char *filename)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MY_LOG
|
|
||||||
|
|
||||||
|
#ifdef MY_LOG
|
||||||
void
|
void
|
||||||
mylog(char *fmt,...)
|
mylog(char *fmt,...)
|
||||||
{
|
{
|
||||||
@ -83,12 +85,10 @@ mylog(char *fmt,...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef Q_LOG
|
#ifdef Q_LOG
|
||||||
|
|
||||||
void
|
void
|
||||||
qlog(char *fmt,...)
|
qlog(char *fmt,...)
|
||||||
{
|
{
|
||||||
@ -114,7 +114,6 @@ qlog(char *fmt,...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Undefine these because windows.h will redefine and cause a warning */
|
/* Undefine these because windows.h will redefine and cause a warning */
|
||||||
@ -137,7 +136,10 @@ qlog(char *fmt,...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* 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, int dst_len, char *src, int src_len)
|
my_strcpy(char *dst, int dst_len, char *src, int src_len)
|
||||||
{
|
{
|
||||||
@ -154,7 +156,6 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
|
|||||||
|
|
||||||
if (src_len <= 0)
|
if (src_len <= 0)
|
||||||
return STRCPY_FAIL;
|
return STRCPY_FAIL;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (src_len < dst_len)
|
if (src_len < dst_len)
|
||||||
@ -173,10 +174,13 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
|
|||||||
return strlen(dst);
|
return strlen(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* strncpy copies up to len characters, and doesn't terminate */
|
|
||||||
/* the destination string if src has len characters or more. */
|
/*
|
||||||
/* instead, I want it to copy up to len-1 characters and always */
|
* strncpy copies up to len characters, and doesn't terminate
|
||||||
/* terminate the destination string. */
|
* the destination string if src has len characters or more.
|
||||||
|
* instead, I want it to copy up to len-1 characters and always
|
||||||
|
* terminate the destination string.
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
strncpy_null(char *dst, const char *src, int len)
|
strncpy_null(char *dst, const char *src, int len)
|
||||||
{
|
{
|
||||||
@ -185,7 +189,6 @@ strncpy_null(char *dst, const char *src, int len)
|
|||||||
|
|
||||||
if (NULL != dst)
|
if (NULL != dst)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Just in case, check for special lengths */
|
/* Just in case, check for special lengths */
|
||||||
if (len == SQL_NULL_DATA)
|
if (len == SQL_NULL_DATA)
|
||||||
{
|
{
|
||||||
@ -204,9 +207,14 @@ strncpy_null(char *dst, const char *src, int len)
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a null terminated string (handling the SQL_NTS thing): */
|
|
||||||
/* 1. If buf is supplied, place the string in there (assumes enough space) and return buf. */
|
/*------
|
||||||
/* 2. If buf is not supplied, malloc space and return this string */
|
* Create a null terminated string (handling the SQL_NTS thing):
|
||||||
|
* 1. If buf is supplied, place the string in there
|
||||||
|
* (assumes enough space) and return buf.
|
||||||
|
* 2. If buf is not supplied, malloc space and return this string
|
||||||
|
*------
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
make_string(char *s, int len, char *buf)
|
make_string(char *s, int len, char *buf)
|
||||||
{
|
{
|
||||||
@ -234,14 +242,16 @@ make_string(char *s, int len, char *buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing. */
|
|
||||||
/* "fmt" must contain somewhere in it the single form '%.*s' */
|
/*
|
||||||
/* This is heavily used in creating queries for info routines (SQLTables, SQLColumns). */
|
* Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing.
|
||||||
/* This routine could be modified to use vsprintf() to handle multiple arguments. */
|
* "fmt" must contain somewhere in it the single form '%.*s'.
|
||||||
|
* This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
|
||||||
|
* This routine could be modified to use vsprintf() to handle multiple arguments.
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
my_strcat(char *buf, char *fmt, char *s, int len)
|
my_strcat(char *buf, char *fmt, char *s, int len)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
|
if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
|
||||||
{
|
{
|
||||||
int length = (len > 0) ? len : strlen(s);
|
int length = (len > 0) ? len : strlen(s);
|
||||||
@ -254,6 +264,7 @@ my_strcat(char *buf, char *fmt, char *s, int len)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
remove_newlines(char *string)
|
remove_newlines(char *string)
|
||||||
{
|
{
|
||||||
@ -267,6 +278,7 @@ remove_newlines(char *string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
trim(char *s)
|
trim(char *s)
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*--------
|
||||||
* Module : multibyte.c
|
* Module : multibyte.c
|
||||||
*
|
*
|
||||||
* Description: Mlutibyte related additional function.
|
* Description: Mlutibyte related additional function.
|
||||||
*
|
*
|
||||||
* Create 2001-03-03 Eiji Tokuya
|
* Create 2001-03-03 Eiji Tokuya
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -13,6 +13,7 @@
|
|||||||
int multibyte_client_encoding; /* Multibyte Client Encoding. */
|
int multibyte_client_encoding; /* Multibyte Client Encoding. */
|
||||||
int multibyte_status; /* Multibyte Odds and ends character. */
|
int multibyte_status; /* Multibyte Odds and ends character. */
|
||||||
|
|
||||||
|
|
||||||
unsigned char *
|
unsigned char *
|
||||||
multibyte_strchr(unsigned char *s, unsigned char c)
|
multibyte_strchr(unsigned char *s, unsigned char c)
|
||||||
{
|
{
|
||||||
@ -36,7 +37,6 @@ multibyte_strchr(unsigned char *s, unsigned char c)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* Chinese Big5 Support. */
|
/* Chinese Big5 Support. */
|
||||||
case BIG5:
|
case BIG5:
|
||||||
{
|
{
|
||||||
@ -59,12 +59,14 @@ multibyte_strchr(unsigned char *s, unsigned char c)
|
|||||||
return (s + i);
|
return (s + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
multibyte_init(void)
|
multibyte_init(void)
|
||||||
{
|
{
|
||||||
multibyte_status = 0;
|
multibyte_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char *
|
unsigned char *
|
||||||
check_client_encoding(unsigned char *str)
|
check_client_encoding(unsigned char *str)
|
||||||
{
|
{
|
||||||
@ -81,12 +83,14 @@ check_client_encoding(unsigned char *str)
|
|||||||
return ("OHTER");
|
return ("OHTER");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
/*--------
|
||||||
* Multibyte Status Function.
|
* Multibyte Status Function.
|
||||||
* Input char
|
* Input char
|
||||||
* Output 0 : 1 Byte Character.
|
* Output 0 : 1 Byte Character.
|
||||||
* 1 : MultibyteCharacter Last Byte.
|
* 1 : MultibyteCharacter Last Byte.
|
||||||
* N : MultibyteCharacter Fast or Middle Byte.
|
* N : MultibyteCharacter Fast or Middle Byte.
|
||||||
|
*--------
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
multibyte_char_check(unsigned char s)
|
multibyte_char_check(unsigned char s)
|
||||||
@ -105,7 +109,6 @@ multibyte_char_check(unsigned char s)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* Chinese Big5(CP950) Support. */
|
/* Chinese Big5(CP950) Support. */
|
||||||
case BIG5:
|
case BIG5:
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* 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.
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* SQLGetStmtOption
|
* SQLGetStmtOption
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -43,7 +44,6 @@ RETCODE set_statement_option(ConnectionClass *conn,
|
|||||||
UDWORD vParam);
|
UDWORD vParam);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE
|
RETCODE
|
||||||
set_statement_option(ConnectionClass *conn,
|
set_statement_option(ConnectionClass *conn,
|
||||||
StatementClass *stmt,
|
StatementClass *stmt,
|
||||||
@ -53,7 +53,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
static char *func = "set_statement_option";
|
static char *func = "set_statement_option";
|
||||||
char changed = FALSE;
|
char changed = FALSE;
|
||||||
|
|
||||||
|
|
||||||
switch (fOption)
|
switch (fOption)
|
||||||
{
|
{
|
||||||
case SQL_ASYNC_ENABLE: /* ignored */
|
case SQL_ASYNC_ENABLE: /* ignored */
|
||||||
@ -68,12 +67,10 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CONCURRENCY:
|
case SQL_CONCURRENCY:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* positioned update isn't supported so cursor concurrency is
|
* positioned update isn't supported so cursor concurrency is
|
||||||
* read-only
|
* read-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
conn->stmtOptions.scroll_concurrency = vParam;
|
conn->stmtOptions.scroll_concurrency = vParam;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
@ -104,7 +101,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
case SQL_CURSOR_TYPE:
|
case SQL_CURSOR_TYPE:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if declare/fetch, then type can only be forward. otherwise,
|
* if declare/fetch, then type can only be forward. otherwise,
|
||||||
* it can only be forward or static.
|
* it can only be forward or static.
|
||||||
@ -113,18 +109,15 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
|
|
||||||
if (globals.lie)
|
if (globals.lie)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
conn->stmtOptions.cursor_type = vParam;
|
conn->stmtOptions.cursor_type = vParam;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
stmt->options.cursor_type = vParam;
|
stmt->options.cursor_type = vParam;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (globals.use_declarefetch)
|
if (globals.use_declarefetch)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
@ -137,7 +130,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
{
|
{
|
||||||
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
|
if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
conn->stmtOptions.cursor_type = vParam; /* valid type */
|
conn->stmtOptions.cursor_type = vParam; /* valid type */
|
||||||
if (stmt)
|
if (stmt)
|
||||||
@ -145,7 +137,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
|
conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
@ -167,11 +158,17 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*-------
|
||||||
* if (globals.lie) stmt->keyset_size = vParam; else {
|
* if (globals.lie)
|
||||||
|
* stmt->keyset_size = vParam;
|
||||||
|
* else
|
||||||
|
* {
|
||||||
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
||||||
* stmt->errormsg = "Driver does not support keyset size
|
* stmt->errormsg = "Driver does not support keyset size option";
|
||||||
* option"; SC_log_error(func, "", stmt); return SQL_ERROR; }
|
* SC_log_error(func, "", stmt);
|
||||||
|
* return SQL_ERROR;
|
||||||
|
* }
|
||||||
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case SQL_MAX_LENGTH: /* ignored, but saved */
|
case SQL_MAX_LENGTH: /* ignored, but saved */
|
||||||
@ -210,7 +207,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
case SQL_ROWSET_SIZE:
|
case SQL_ROWSET_SIZE:
|
||||||
mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam);
|
mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save old rowset size for SQLExtendedFetch purposes If the
|
* Save old rowset size for SQLExtendedFetch purposes If the
|
||||||
* rowset_size is being changed since the last call to fetch
|
* rowset_size is being changed since the last call to fetch
|
||||||
@ -230,7 +226,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
conn->stmtOptions.rowset_size = vParam;
|
conn->stmtOptions.rowset_size = vParam;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
stmt->options.rowset_size = vParam;
|
stmt->options.rowset_size = vParam;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
|
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
|
||||||
@ -249,7 +244,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
|
||||||
case SQL_USE_BOOKMARKS:
|
case SQL_USE_BOOKMARKS:
|
||||||
|
|
||||||
if (stmt)
|
if (stmt)
|
||||||
stmt->options.use_bookmarks = vParam;
|
stmt->options.use_bookmarks = vParam;
|
||||||
if (conn)
|
if (conn)
|
||||||
@ -298,7 +292,6 @@ set_statement_option(ConnectionClass *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Implements only SQL_AUTOCOMMIT */
|
/* Implements only SQL_AUTOCOMMIT */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetConnectOption(
|
SQLSetConnectOption(
|
||||||
@ -320,10 +313,8 @@ SQLSetConnectOption(
|
|||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (fOption)
|
switch (fOption)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Statement Options (apply to all stmts on the connection and
|
* Statement Options (apply to all stmts on the connection and
|
||||||
* become defaults for new stmts)
|
* become defaults for new stmts)
|
||||||
@ -362,15 +353,14 @@ SQLSetConnectOption(
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/**********************************/
|
/*
|
||||||
/***** Connection Options *******/
|
* Connection Options
|
||||||
/**********************************/
|
*/
|
||||||
|
|
||||||
case SQL_ACCESS_MODE: /* ignored */
|
case SQL_ACCESS_MODE: /* ignored */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_AUTOCOMMIT:
|
case SQL_AUTOCOMMIT:
|
||||||
|
|
||||||
if (CC_is_in_trans(conn))
|
if (CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
|
conn->errormsg = "Cannot switch commit mode while a transaction is in progress";
|
||||||
@ -397,7 +387,6 @@ SQLSetConnectOption(
|
|||||||
CC_log_error(func, "", conn);
|
CC_log_error(func, "", conn);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CURRENT_QUALIFIER: /* ignored */
|
case SQL_CURRENT_QUALIFIER: /* ignored */
|
||||||
@ -434,7 +423,6 @@ SQLSetConnectOption(
|
|||||||
CC_log_error(func, option, conn);
|
CC_log_error(func, option, conn);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
@ -447,7 +435,6 @@ SQLSetConnectOption(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
/* This function just can tell you whether you are in Autcommit mode or not */
|
/* This function just can tell you whether you are in Autcommit mode or not */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
@ -520,13 +507,11 @@ SQLGetConnectOption(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetStmtOption(
|
SQLSetStmtOption(
|
||||||
@ -539,10 +524,11 @@ SQLSetStmtOption(
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/* 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 */
|
* Though we could fake Access out by just returning SQL_SUCCESS
|
||||||
/* and expects the driver to reduce it to the real value */
|
* 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.
|
||||||
|
*/
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
{
|
{
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -553,8 +539,6 @@ SQLSetStmtOption(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetStmtOption(
|
SQLGetStmtOption(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -567,10 +551,11 @@ SQLGetStmtOption(
|
|||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/* 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 */
|
* thought we could fake Access out by just returning SQL_SUCCESS
|
||||||
/* and expects the driver to reduce it to the real value */
|
* 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
|
||||||
|
*/
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
{
|
{
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -689,5 +674,3 @@ SQLGetStmtOption(
|
|||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
/* Module: parse.c
|
/*--------
|
||||||
|
* Module: parse.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines related to parsing SQL statements.
|
* Description: This module contains routines related to parsing SQL
|
||||||
* This can be useful for two reasons:
|
* statements. This can be useful for two reasons:
|
||||||
*
|
*
|
||||||
* 1. So the query does not actually have to be executed to return data about it
|
* 1. So the query does not actually have to be executed
|
||||||
|
* to return data about it
|
||||||
*
|
*
|
||||||
* 2. To be able to return information about precision, nullability, aliases, etc.
|
* 2. To be able to return information about precision,
|
||||||
* in the functions SQLDescribeCol and SQLColAttributes. Currently, Postgres
|
* nullability, aliases, etc. in the functions
|
||||||
* doesn't return any information about these things in a query.
|
* SQLDescribeCol and SQLColAttributes. Currently,
|
||||||
|
* Postgres doesn't return any information about
|
||||||
|
* these things in a query.
|
||||||
*
|
*
|
||||||
* Classes: none
|
* Classes: none
|
||||||
*
|
*
|
||||||
* API functions: none
|
* API functions: none
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||||
|
|
||||||
@ -50,6 +54,7 @@ char *getNextToken(char *s, char *token, int smax, char *delim, char *quote,
|
|||||||
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
|
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
|
||||||
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
|
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
|
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
|
||||||
{
|
{
|
||||||
@ -87,7 +92,6 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
|
|||||||
while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
|
while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
|
||||||
s[i] != '\0' && out != smax)
|
s[i] != '\0' && out != smax)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Handle quoted stuff */
|
/* Handle quoted stuff */
|
||||||
if (out == 0 && (s[i] == '\"' || s[i] == '\''))
|
if (out == 0 && (s[i] == '\"' || s[i] == '\''))
|
||||||
{
|
{
|
||||||
@ -225,13 +229,13 @@ getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
|
|||||||
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
|
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
|
searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
|
||||||
{
|
{
|
||||||
int k, cmp;
|
int k, cmp;
|
||||||
char *col;
|
char *col;
|
||||||
|
|
||||||
|
|
||||||
for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
|
for (k = 0; k < QR_get_num_tuples(col_info->result); k++)
|
||||||
{
|
{
|
||||||
col = QR_get_value_manual(col_info->result, k, 3);
|
col = QR_get_value_manual(col_info->result, k, 3);
|
||||||
@ -289,7 +293,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
StatementClass *col_stmt;
|
StatementClass *col_stmt;
|
||||||
RETCODE result;
|
RETCODE result;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
ptr = stmt->statement;
|
ptr = stmt->statement;
|
||||||
@ -301,7 +304,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
|
while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
unquoted = !(quote || dquote);
|
unquoted = !(quote || dquote);
|
||||||
|
|
||||||
mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr);
|
mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr);
|
||||||
@ -345,7 +347,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
!stricmp(token, "group") ||
|
!stricmp(token, "group") ||
|
||||||
!stricmp(token, "having")))
|
!stricmp(token, "having")))
|
||||||
{
|
{
|
||||||
|
|
||||||
in_select = FALSE;
|
in_select = FALSE;
|
||||||
in_from = FALSE;
|
in_from = FALSE;
|
||||||
in_where = TRUE;
|
in_where = TRUE;
|
||||||
@ -356,7 +357,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
if (in_select)
|
if (in_select)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (in_distinct)
|
if (in_distinct)
|
||||||
{
|
{
|
||||||
mylog("in distinct\n");
|
mylog("in distinct\n");
|
||||||
@ -378,7 +378,8 @@ parse_statement(StatementClass *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (in_expr || in_func)
|
if (in_expr || in_func)
|
||||||
{ /* just eat the expression */
|
{
|
||||||
|
/* just eat the expression */
|
||||||
mylog("in_expr=%d or func=%d\n", in_expr, in_func);
|
mylog("in_expr=%d or func=%d\n", in_expr, in_func);
|
||||||
if (quote || dquote)
|
if (quote || dquote)
|
||||||
continue;
|
continue;
|
||||||
@ -389,7 +390,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
in_expr = FALSE;
|
in_expr = FALSE;
|
||||||
in_field = FALSE;
|
in_field = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (token[0] == '(')
|
else if (token[0] == '(')
|
||||||
{
|
{
|
||||||
blevel++;
|
blevel++;
|
||||||
@ -414,7 +414,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
if (!in_field)
|
if (!in_field)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!token[0])
|
if (!token[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -462,7 +461,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
blevel = 1;
|
blevel = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy(fi[stmt->nfld]->name, token);
|
strcpy(fi[stmt->nfld]->name, token);
|
||||||
@ -478,9 +476,9 @@ parse_statement(StatementClass *stmt)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************/
|
/*
|
||||||
/* We are in a field now */
|
* We are in a field now
|
||||||
/**************************/
|
*/
|
||||||
if (in_dot)
|
if (in_dot)
|
||||||
{
|
{
|
||||||
stmt->nfld--;
|
stmt->nfld--;
|
||||||
@ -494,7 +492,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog("in_dot: got comma\n");
|
mylog("in_dot: got comma\n");
|
||||||
in_field = FALSE;
|
in_field = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,12 +544,10 @@ parse_statement(StatementClass *stmt)
|
|||||||
fi[stmt->nfld - 1]->expr = TRUE;
|
fi[stmt->nfld - 1]->expr = TRUE;
|
||||||
fi[stmt->nfld - 1]->name[0] = '\0';
|
fi[stmt->nfld - 1]->name[0] = '\0';
|
||||||
mylog("*** setting expression\n");
|
mylog("*** setting expression\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_from)
|
if (in_from)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!in_table)
|
if (!in_table)
|
||||||
{
|
{
|
||||||
if (!token[0])
|
if (!token[0])
|
||||||
@ -603,17 +598,15 @@ parse_statement(StatementClass *stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/*************************************************/
|
* Resolve any possible field names with tables
|
||||||
/* Resolve any possible field names with tables */
|
*/
|
||||||
/*************************************************/
|
|
||||||
|
|
||||||
parse = TRUE;
|
parse = TRUE;
|
||||||
|
|
||||||
/* Resolve field names with tables */
|
/* Resolve field names with tables */
|
||||||
for (i = 0; i < stmt->nfld; i++)
|
for (i = 0; i < stmt->nfld; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
|
if (fi[i]->func || fi[i]->expr || fi[i]->numeric)
|
||||||
{
|
{
|
||||||
fi[i]->ti = NULL;
|
fi[i]->ti = NULL;
|
||||||
@ -621,7 +614,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
parse = FALSE;
|
parse = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (fi[i]->quote)
|
else if (fi[i]->quote)
|
||||||
{ /* handle as text */
|
{ /* handle as text */
|
||||||
fi[i]->ti = NULL;
|
fi[i]->ti = NULL;
|
||||||
@ -629,7 +621,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
fi[i]->precision = 0;
|
fi[i]->precision = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* it's a dot, resolve to table or alias */
|
/* it's a dot, resolve to table or alias */
|
||||||
else if (fi[i]->dot[0])
|
else if (fi[i]->dot[0])
|
||||||
{
|
{
|
||||||
@ -665,15 +656,13 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
|
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
|
||||||
|
|
||||||
|
|
||||||
/******************************************************/
|
/*
|
||||||
/* Now save the SQLColumns Info for the parse tables */
|
* Now save the SQLColumns Info for the parse tables
|
||||||
/******************************************************/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Call SQLColumns for each table and store the result */
|
/* Call SQLColumns for each table and store the result */
|
||||||
for (i = 0; i < stmt->ntab; i++)
|
for (i = 0; i < stmt->ntab; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* See if already got it */
|
/* See if already got it */
|
||||||
char found = FALSE;
|
char found = FALSE;
|
||||||
|
|
||||||
@ -689,7 +678,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
|
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
|
||||||
|
|
||||||
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
result = SQLAllocStmt(stmt->hdbc, &hcol_stmt);
|
||||||
@ -713,7 +701,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog(" Success\n");
|
mylog(" Success\n");
|
||||||
if (!(conn->ntables % COL_INCR))
|
if (!(conn->ntables % COL_INCR))
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables);
|
mylog("PARSE: Allocing col_info at ntables=%d\n", conn->ntables);
|
||||||
|
|
||||||
conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
|
conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
|
||||||
@ -762,18 +749,13 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog("associate col_info: i=%d, k=%d\n", i, k);
|
mylog("associate col_info: i=%d, k=%d\n", i, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mylog("Done SQLColumns\n");
|
mylog("Done SQLColumns\n");
|
||||||
|
|
||||||
/******************************************************/
|
/*
|
||||||
/* Now resolve the fields to point to column info */
|
* Now resolve the fields to point to column info
|
||||||
/******************************************************/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < stmt->nfld;)
|
for (i = 0; i < stmt->nfld;)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Dont worry about functions or quotes */
|
/* Dont worry about functions or quotes */
|
||||||
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
|
if (fi[i]->func || fi[i]->quote || fi[i]->numeric)
|
||||||
{
|
{
|
||||||
@ -784,7 +766,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
/* Stars get expanded to all fields in the table */
|
/* Stars get expanded to all fields in the table */
|
||||||
else if (fi[i]->name[0] == '*')
|
else if (fi[i]->name[0] == '*')
|
||||||
{
|
{
|
||||||
|
|
||||||
char do_all_tables;
|
char do_all_tables;
|
||||||
int total_cols,
|
int total_cols,
|
||||||
old_alloc,
|
old_alloc,
|
||||||
@ -810,7 +791,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
increased_cols = total_cols - 1;
|
increased_cols = total_cols - 1;
|
||||||
|
|
||||||
/* Allocate some more field pointers if necessary */
|
/* Allocate some more field pointers if necessary */
|
||||||
/*------------------------------------------------------------- */
|
|
||||||
old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR;
|
old_alloc = ((stmt->nfld - 1) / FLD_INCR + 1) * FLD_INCR;
|
||||||
new_size = stmt->nfld + increased_cols;
|
new_size = stmt->nfld + increased_cols;
|
||||||
|
|
||||||
@ -830,8 +810,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
stmt->fi = fi;
|
stmt->fi = fi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy any other fields (if there are any) up past the
|
* copy any other fields (if there are any) up past the
|
||||||
* expansion
|
* expansion
|
||||||
@ -843,21 +821,16 @@ parse_statement(StatementClass *stmt)
|
|||||||
}
|
}
|
||||||
mylog("done copying fields\n");
|
mylog("done copying fields\n");
|
||||||
|
|
||||||
/*------------------------------------------------------------- */
|
|
||||||
/* Set the new number of fields */
|
/* Set the new number of fields */
|
||||||
stmt->nfld += increased_cols;
|
stmt->nfld += increased_cols;
|
||||||
mylog("stmt->nfld now at %d\n", stmt->nfld);
|
mylog("stmt->nfld now at %d\n", stmt->nfld);
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------- */
|
|
||||||
/* copy the new field info */
|
/* copy the new field info */
|
||||||
|
|
||||||
|
|
||||||
do_all_tables = (fi[i]->ti ? FALSE : TRUE);
|
do_all_tables = (fi[i]->ti ? FALSE : TRUE);
|
||||||
|
|
||||||
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
|
for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++)
|
||||||
{
|
{
|
||||||
|
|
||||||
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
|
TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
|
||||||
|
|
||||||
cols = QR_get_num_tuples(the_ti->col_info->result);
|
cols = QR_get_num_tuples(the_ti->col_info->result);
|
||||||
@ -890,8 +863,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
i += cols;
|
i += cols;
|
||||||
mylog("i now at %d\n", i);
|
mylog("i now at %d\n", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------- */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -901,7 +872,6 @@ parse_statement(StatementClass *stmt)
|
|||||||
*/
|
*/
|
||||||
else if (fi[i]->ti)
|
else if (fi[i]->ti)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
|
if (!searchColInfo(fi[i]->ti->col_info, fi[i]))
|
||||||
parse = FALSE;
|
parse = FALSE;
|
||||||
|
|
||||||
@ -925,13 +895,11 @@ parse_statement(StatementClass *stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!parse)
|
if (!parse)
|
||||||
stmt->parse_status = STMT_PARSE_INCOMPLETE;
|
stmt->parse_status = STMT_PARSE_INCOMPLETE;
|
||||||
else
|
else
|
||||||
stmt->parse_status = STMT_PARSE_COMPLETE;
|
stmt->parse_status = STMT_PARSE_COMPLETE;
|
||||||
|
|
||||||
|
|
||||||
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
|
mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, stmt->parse_status);
|
||||||
return parse;
|
return parse;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
/* Module: pgtypes.c
|
/*--------
|
||||||
|
* Module: pgtypes.c
|
||||||
*
|
*
|
||||||
* Description: This module contains routines for getting information
|
* Description: This module contains routines for getting information
|
||||||
* about the supported Postgres data types. Only the function
|
* about the supported Postgres data types. Only the
|
||||||
* pgtype_to_sqltype() returns an unknown condition. All other
|
* function pgtype_to_sqltype() returns an unknown condition.
|
||||||
* functions return a suitable default so that even data types that
|
* All other functions return a suitable default so that
|
||||||
* are not directly supported can be used (it is handled as char data).
|
* even data types that are not directly supported can be
|
||||||
|
* used (it is handled as char data).
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -40,15 +42,18 @@ extern GLOBAL_VALUES globals;
|
|||||||
|
|
||||||
Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
|
Int4 getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
|
||||||
|
|
||||||
|
/*
|
||||||
/* these are the types we support. all of the pgtype_ functions should */
|
* these are the types we support. all of the pgtype_ functions should
|
||||||
/* return values for each one of these. */
|
* return values for each one of these.
|
||||||
/* Even types not directly supported are handled as character types
|
* Even types not directly supported are handled as character types
|
||||||
so all types should work (points, etc.) */
|
* so all types should work (points, etc.)
|
||||||
|
|
||||||
/* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all
|
|
||||||
the SQL TYPES are reported and mapped to a corresponding Postgres Type
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ALL THESE TYPES ARE NO LONGER REPORTED in SQLGetTypeInfo. Instead, all
|
||||||
|
* the SQL TYPES are reported and mapped to a corresponding Postgres Type
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Int4 pgtypes_defined[] = {
|
Int4 pgtypes_defined[] = {
|
||||||
PG_TYPE_CHAR,
|
PG_TYPE_CHAR,
|
||||||
@ -102,6 +107,7 @@ Int2 sqlTypes[] = {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Int4
|
Int4
|
||||||
sqltype_to_pgtype(SWORD fSqlType)
|
sqltype_to_pgtype(SWORD fSqlType)
|
||||||
{
|
{
|
||||||
@ -109,7 +115,6 @@ sqltype_to_pgtype(SWORD fSqlType)
|
|||||||
|
|
||||||
switch (fSqlType)
|
switch (fSqlType)
|
||||||
{
|
{
|
||||||
|
|
||||||
case SQL_BINARY:
|
case SQL_BINARY:
|
||||||
pgType = PG_TYPE_BYTEA;
|
pgType = PG_TYPE_BYTEA;
|
||||||
break;
|
break;
|
||||||
@ -185,14 +190,18 @@ sqltype_to_pgtype(SWORD fSqlType)
|
|||||||
return pgType;
|
return pgType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There are two ways of calling this function:
|
|
||||||
1. When going through the supported PG types (SQLGetTypeInfo)
|
|
||||||
2. When taking any type id (SQLColumns, SQLGetData)
|
|
||||||
|
|
||||||
The first type will always work because all the types defined are returned here.
|
/*
|
||||||
The second type will return a default based on global parameter when it does not
|
* There are two ways of calling this function:
|
||||||
know. This allows for supporting
|
*
|
||||||
types that are unknown. All other pg routines in here return a suitable default.
|
* 1. When going through the supported PG types (SQLGetTypeInfo)
|
||||||
|
*
|
||||||
|
* 2. When taking any type id (SQLColumns, SQLGetData)
|
||||||
|
*
|
||||||
|
* The first type will always work because all the types defined are returned here.
|
||||||
|
* The second type will return a default based on global parameter when it does not
|
||||||
|
* know. This allows for supporting
|
||||||
|
* types that are unknown. All other pg routines in here return a suitable default.
|
||||||
*/
|
*/
|
||||||
Int2
|
Int2
|
||||||
pgtype_to_sqltype(StatementClass *stmt, Int4 type)
|
pgtype_to_sqltype(StatementClass *stmt, Int4 type)
|
||||||
@ -253,20 +262,20 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
|
|||||||
return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
|
return globals.bools_as_char ? SQL_CHAR : SQL_BIT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* first, check to see if 'type' is in list. If not, look up
|
* first, check to see if 'type' is in list. If not, look up
|
||||||
* with query. Add oid, name to list. If it's already in
|
* with query. Add oid, name to list. If it's already in
|
||||||
* list, just return.
|
* list, just return.
|
||||||
*/
|
*/
|
||||||
if (type == stmt->hdbc->lobj_type) /* hack until permanent
|
/* hack until permanent type is available */
|
||||||
* type is available */
|
if (type == stmt->hdbc->lobj_type)
|
||||||
return SQL_LONGVARBINARY;
|
return SQL_LONGVARBINARY;
|
||||||
|
|
||||||
return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
|
return globals.unknowns_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_to_ctype(StatementClass *stmt, Int4 type)
|
pgtype_to_ctype(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -305,15 +314,15 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
|
|||||||
return SQL_C_BINARY;
|
return SQL_C_BINARY;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
/* hack until permanent type is available */
|
||||||
if (type == stmt->hdbc->lobj_type) /* hack until permanent
|
if (type == stmt->hdbc->lobj_type)
|
||||||
* type is available */
|
|
||||||
return SQL_C_BINARY;
|
return SQL_C_BINARY;
|
||||||
|
|
||||||
return SQL_C_CHAR;
|
return SQL_C_CHAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pgtype_to_name(StatementClass *stmt, Int4 type)
|
pgtype_to_name(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -369,8 +378,8 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
|
|||||||
return PG_TYPE_LO_NAME;
|
return PG_TYPE_LO_NAME;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (type == stmt->hdbc->lobj_type) /* hack until permanent
|
/* hack until permanent type is available */
|
||||||
* type is available */
|
if (type == stmt->hdbc->lobj_type)
|
||||||
return PG_TYPE_LO_NAME;
|
return PG_TYPE_LO_NAME;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -381,6 +390,7 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Int2
|
static Int2
|
||||||
getNumericScale(StatementClass *stmt, Int4 type, int col)
|
getNumericScale(StatementClass *stmt, Int4 type, int col)
|
||||||
{
|
{
|
||||||
@ -417,6 +427,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
|
|||||||
PG_NUMERIC_MAX_SCALE);
|
PG_NUMERIC_MAX_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Int4
|
static Int4
|
||||||
getNumericPrecision(StatementClass *stmt, Int4 type, int col)
|
getNumericPrecision(StatementClass *stmt, Int4 type, int col)
|
||||||
{
|
{
|
||||||
@ -453,6 +464,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
|
|||||||
PG_NUMERIC_MAX_PRECISION);
|
PG_NUMERIC_MAX_PRECISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int4
|
Int4
|
||||||
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
||||||
{
|
{
|
||||||
@ -524,19 +536,19 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
|
|
||||||
override this length with the atttypmod length from pg_attribute .
|
|
||||||
|
|
||||||
If col >= 0, then will attempt to get the info from the result set.
|
/*
|
||||||
This is used for functions SQLDescribeCol and SQLColAttributes.
|
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, PG_TYPE_NUMERIC, SQLColumns will
|
||||||
|
* override this length with the atttypmod length from pg_attribute .
|
||||||
|
*
|
||||||
|
* If col >= 0, then will attempt to get the info from the result set.
|
||||||
|
* This is used for functions SQLDescribeCol and SQLColAttributes.
|
||||||
*/
|
*/
|
||||||
Int4
|
Int4
|
||||||
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_CHAR:
|
case PG_TYPE_CHAR:
|
||||||
return 1;
|
return 1;
|
||||||
case PG_TYPE_CHAR2:
|
case PG_TYPE_CHAR2:
|
||||||
@ -597,10 +609,10 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int4
|
Int4
|
||||||
pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
@ -634,16 +646,16 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
|
|
||||||
override this length with the atttypmod length from pg_attribute
|
/*
|
||||||
|
* For PG_TYPE_VARCHAR, PG_TYPE_BPCHAR, SQLColumns will
|
||||||
|
* override this length with the atttypmod length from pg_attribute
|
||||||
*/
|
*/
|
||||||
Int4
|
Int4
|
||||||
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
@ -674,19 +686,18 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
|
|||||||
case PG_TYPE_TIMESTAMP:
|
case PG_TYPE_TIMESTAMP:
|
||||||
return 16;
|
return 16;
|
||||||
|
|
||||||
|
|
||||||
/* Character types (and NUMERIC) use the default precision */
|
/* Character types (and NUMERIC) use the default precision */
|
||||||
default:
|
default:
|
||||||
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
|
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_scale(StatementClass *stmt, Int4 type, int col)
|
pgtype_scale(StatementClass *stmt, Int4 type, int col)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
case PG_TYPE_OID:
|
case PG_TYPE_OID:
|
||||||
case PG_TYPE_XID:
|
case PG_TYPE_XID:
|
||||||
@ -729,24 +740,24 @@ pgtype_radix(StatementClass *stmt, Int4 type)
|
|||||||
case PG_TYPE_MONEY:
|
case PG_TYPE_MONEY:
|
||||||
case PG_TYPE_FLOAT8:
|
case PG_TYPE_FLOAT8:
|
||||||
return 10;
|
return 10;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_nullable(StatementClass *stmt, Int4 type)
|
pgtype_nullable(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
return SQL_NULLABLE; /* everything should be nullable */
|
return SQL_NULLABLE; /* everything should be nullable */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_auto_increment(StatementClass *stmt, Int4 type)
|
pgtype_auto_increment(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
case PG_TYPE_OID:
|
case PG_TYPE_OID:
|
||||||
case PG_TYPE_XID:
|
case PG_TYPE_XID:
|
||||||
@ -770,6 +781,7 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_case_sensitive(StatementClass *stmt, Int4 type)
|
pgtype_case_sensitive(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -792,6 +804,7 @@ pgtype_case_sensitive(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_money(StatementClass *stmt, Int4 type)
|
pgtype_money(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -804,6 +817,7 @@ pgtype_money(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_searchable(StatementClass *stmt, Int4 type)
|
pgtype_searchable(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -825,6 +839,7 @@ pgtype_searchable(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Int2
|
Int2
|
||||||
pgtype_unsigned(StatementClass *stmt, Int4 type)
|
pgtype_unsigned(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -848,12 +863,12 @@ pgtype_unsigned(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pgtype_literal_prefix(StatementClass *stmt, Int4 type)
|
pgtype_literal_prefix(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
case PG_TYPE_OID:
|
case PG_TYPE_OID:
|
||||||
case PG_TYPE_XID:
|
case PG_TYPE_XID:
|
||||||
@ -869,12 +884,12 @@ pgtype_literal_prefix(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pgtype_literal_suffix(StatementClass *stmt, Int4 type)
|
pgtype_literal_suffix(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
||||||
case PG_TYPE_INT2:
|
case PG_TYPE_INT2:
|
||||||
case PG_TYPE_OID:
|
case PG_TYPE_OID:
|
||||||
case PG_TYPE_XID:
|
case PG_TYPE_XID:
|
||||||
@ -890,6 +905,7 @@ pgtype_literal_suffix(StatementClass *stmt, Int4 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
pgtype_create_params(StatementClass *stmt, Int4 type)
|
pgtype_create_params(StatementClass *stmt, Int4 type)
|
||||||
{
|
{
|
||||||
@ -906,8 +922,10 @@ pgtype_create_params(StatementClass *stmt, Int4 type)
|
|||||||
Int2
|
Int2
|
||||||
sqltype_to_default_ctype(Int2 sqltype)
|
sqltype_to_default_ctype(Int2 sqltype)
|
||||||
{
|
{
|
||||||
/* from the table on page 623 of ODBC 2.0 Programmer's Reference */
|
/*
|
||||||
/* (Appendix D) */
|
* from the table on page 623 of ODBC 2.0 Programmer's Reference
|
||||||
|
* (Appendix D)
|
||||||
|
*/
|
||||||
switch (sqltype)
|
switch (sqltype)
|
||||||
{
|
{
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
@ -951,7 +969,8 @@ sqltype_to_default_ctype(Int2 sqltype)
|
|||||||
case SQL_TIMESTAMP:
|
case SQL_TIMESTAMP:
|
||||||
return SQL_C_TIMESTAMP;
|
return SQL_C_TIMESTAMP;
|
||||||
|
|
||||||
default: /* should never happen */
|
default:
|
||||||
|
/* should never happen */
|
||||||
return SQL_C_CHAR;
|
return SQL_C_CHAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
/* Module: psqlodbc.c
|
/*--------
|
||||||
|
* Module: psqlodbc.c
|
||||||
*
|
*
|
||||||
* Description: This module contains the main entry point (DllMain) for the library.
|
* Description: This module contains the main entry point (DllMain)
|
||||||
* It also contains functions to get and set global variables for the
|
* for the library. It also contains functions to get
|
||||||
* driver in the registry.
|
* and set global variables for the driver in the registry.
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
*
|
*--------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -59,7 +60,6 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
|||||||
if (LOBYTE(wsaData.wVersion) != 1 ||
|
if (LOBYTE(wsaData.wVersion) != 1 ||
|
||||||
HIBYTE(wsaData.wVersion) != 1)
|
HIBYTE(wsaData.wVersion) != 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -71,9 +71,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
@ -111,7 +109,8 @@ init(void)
|
|||||||
|
|
||||||
#else /* not __GNUC__ */
|
#else /* not __GNUC__ */
|
||||||
|
|
||||||
/* These two functions do shared library initialziation on UNIX, well at least
|
/*
|
||||||
|
* These two functions do shared library initialziation on UNIX, well at least
|
||||||
* on Linux. I don't know about other systems.
|
* on Linux. I don't know about other systems.
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
@ -131,11 +130,13 @@ _fini(void)
|
|||||||
|
|
||||||
#endif /* not WIN32 */
|
#endif /* not WIN32 */
|
||||||
|
|
||||||
/* This function is used to cause the Driver Manager to
|
|
||||||
call functions by number rather than name, which is faster.
|
/*
|
||||||
The ordinal value of this function must be 199 to have the
|
* This function is used to cause the Driver Manager to
|
||||||
Driver Manager do this. Also, the ordinal values of the
|
* call functions by number rather than name, which is faster.
|
||||||
functions must match the value of fFunction in SQLGetFunctions()
|
* The ordinal value of this function must be 199 to have the
|
||||||
|
* Driver Manager do this. Also, the ordinal values of the
|
||||||
|
* functions must match the value of fFunction in SQLGetFunctions()
|
||||||
*/
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLDummyOrdinal(void)
|
SQLDummyOrdinal(void)
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
/* Module: qresult.c
|
/*---------
|
||||||
|
* Module: qresult.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions related to
|
* Description: This module contains functions related to
|
||||||
* managing result information (i.e, fetching rows from the backend,
|
* managing result information (i.e, fetching rows
|
||||||
* managing the tuple cache, etc.) and retrieving it.
|
* from the backend, managing the tuple cache, etc.)
|
||||||
* Depending on the situation, a QResultClass will hold either data
|
* and retrieving it. Depending on the situation, a
|
||||||
* from the backend or a manually built result (see "qresult.h" to
|
* QResultClass will hold either data from the backend
|
||||||
* see which functions/macros are for manual or backend results.
|
* or a manually built result (see "qresult.h" to
|
||||||
* For manually built results, the QResultClass simply points to
|
* see which functions/macros are for manual or backend
|
||||||
* TupleList and ColumnInfo structures, which actually hold the data.
|
* results. For manually built results, the
|
||||||
|
* QResultClass simply points to TupleList and
|
||||||
|
* ColumnInfo structures, which actually hold the data.
|
||||||
*
|
*
|
||||||
* Classes: QResultClass (Functions prefix: "QR_")
|
* Classes: QResultClass (Functions prefix: "QR_")
|
||||||
*
|
*
|
||||||
* 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 "qresult.h"
|
#include "qresult.h"
|
||||||
@ -31,8 +34,11 @@
|
|||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
/* Used for building a Manual Result only */
|
|
||||||
/* All info functions call this function to create the manual result set. */
|
/*
|
||||||
|
* Used for building a Manual Result only
|
||||||
|
* All info functions call this function to create the manual result set.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
QR_set_num_fields(QResultClass *self, int new_num_fields)
|
QR_set_num_fields(QResultClass *self, int new_num_fields)
|
||||||
{
|
{
|
||||||
@ -47,34 +53,38 @@ QR_set_num_fields(QResultClass *self, int new_num_fields)
|
|||||||
mylog("exit QR_set_num_fields\n");
|
mylog("exit QR_set_num_fields\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_set_position(QResultClass *self, int pos)
|
QR_set_position(QResultClass *self, int pos)
|
||||||
{
|
{
|
||||||
self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);
|
self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_set_cache_size(QResultClass *self, int cache_size)
|
QR_set_cache_size(QResultClass *self, int cache_size)
|
||||||
{
|
{
|
||||||
self->cache_size = cache_size;
|
self->cache_size = cache_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_set_rowset_size(QResultClass *self, int rowset_size)
|
QR_set_rowset_size(QResultClass *self, int rowset_size)
|
||||||
{
|
{
|
||||||
self->rowset_size = rowset_size;
|
self->rowset_size = rowset_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_inc_base(QResultClass *self, int base_inc)
|
QR_inc_base(QResultClass *self, int base_inc)
|
||||||
{
|
{
|
||||||
self->base += base_inc;
|
self->base += base_inc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************/
|
|
||||||
/* CLASS QResult */
|
|
||||||
/************************************/
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CLASS QResult
|
||||||
|
*/
|
||||||
QResultClass *
|
QResultClass *
|
||||||
QR_Constructor(void)
|
QR_Constructor(void)
|
||||||
{
|
{
|
||||||
@ -111,13 +121,13 @@ QR_Constructor(void)
|
|||||||
|
|
||||||
rv->cache_size = globals.fetch_max;
|
rv->cache_size = globals.fetch_max;
|
||||||
rv->rowset_size = 1;
|
rv->rowset_size = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("exit QR_Constructor\n");
|
mylog("exit QR_Constructor\n");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_Destructor(QResultClass *self)
|
QR_Destructor(QResultClass *self)
|
||||||
{
|
{
|
||||||
@ -127,8 +137,10 @@ QR_Destructor(QResultClass *self)
|
|||||||
if (self->manual_tuples)
|
if (self->manual_tuples)
|
||||||
TL_Destructor(self->manual_tuples);
|
TL_Destructor(self->manual_tuples);
|
||||||
|
|
||||||
/* If conn is defined, then we may have used "backend_tuples", */
|
/*
|
||||||
/* so in case we need to, free it up. Also, close the cursor. */
|
* If conn is defined, then we may have used "backend_tuples",
|
||||||
|
* so in case we need to, free it up. Also, close the cursor.
|
||||||
|
*/
|
||||||
if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
|
if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
|
||||||
QR_close(self); /* close the cursor if there is one */
|
QR_close(self); /* close the cursor if there is one */
|
||||||
|
|
||||||
@ -153,9 +165,9 @@ QR_Destructor(QResultClass *self)
|
|||||||
free(self);
|
free(self);
|
||||||
|
|
||||||
mylog("QResult: exit DESTRUCTOR\n");
|
mylog("QResult: exit DESTRUCTOR\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_set_command(QResultClass *self, char *msg)
|
QR_set_command(QResultClass *self, char *msg)
|
||||||
{
|
{
|
||||||
@ -165,6 +177,7 @@ QR_set_command(QResultClass *self, char *msg)
|
|||||||
self->command = msg ? strdup(msg) : NULL;
|
self->command = msg ? strdup(msg) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_set_notice(QResultClass *self, char *msg)
|
QR_set_notice(QResultClass *self, char *msg)
|
||||||
{
|
{
|
||||||
@ -174,6 +187,7 @@ QR_set_notice(QResultClass *self, char *msg)
|
|||||||
self->notice = msg ? strdup(msg) : NULL;
|
self->notice = msg ? strdup(msg) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QR_free_memory(QResultClass *self)
|
QR_free_memory(QResultClass *self)
|
||||||
{
|
{
|
||||||
@ -187,7 +201,6 @@ QR_free_memory(QResultClass *self)
|
|||||||
|
|
||||||
if (self->backend_tuples)
|
if (self->backend_tuples)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (row = 0; row < fcount; row++)
|
for (row = 0; row < fcount; row++)
|
||||||
{
|
{
|
||||||
mylog("row = %d, num_fields = %d\n", row, num_fields);
|
mylog("row = %d, num_fields = %d\n", row, num_fields);
|
||||||
@ -211,17 +224,20 @@ QR_free_memory(QResultClass *self)
|
|||||||
mylog("QResult: free memory out\n");
|
mylog("QResult: free memory out\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function is called by send_query() */
|
/* This function is called by send_query() */
|
||||||
char
|
char
|
||||||
QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
||||||
{
|
{
|
||||||
int tuple_size;
|
int tuple_size;
|
||||||
|
|
||||||
/* If called from send_query the first time (conn != NULL), */
|
/*
|
||||||
/* then set the inTuples state, */
|
* If called from send_query the first time (conn != NULL),
|
||||||
/* and read the tuples. If conn is NULL, */
|
* then set the inTuples state,
|
||||||
/* it implies that we are being called from next_tuple(), */
|
* and read the tuples. If conn is NULL,
|
||||||
/* like to get more rows so don't call next_tuple again! */
|
* it implies that we are being called from next_tuple(),
|
||||||
|
* like to get more rows so don't call next_tuple again!
|
||||||
|
*/
|
||||||
if (conn != NULL)
|
if (conn != NULL)
|
||||||
{
|
{
|
||||||
self->conn = conn;
|
self->conn = conn;
|
||||||
@ -242,8 +258,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
self->cursor = strdup(cursor);
|
self->cursor = strdup(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the field attributes. */
|
/*
|
||||||
/* $$$$ Should do some error control HERE! $$$$ */
|
* Read the field attributes.
|
||||||
|
*
|
||||||
|
* $$$$ Should do some error control HERE! $$$$
|
||||||
|
*/
|
||||||
if (CI_read_fields(self->fields, self->conn))
|
if (CI_read_fields(self->fields, self->conn))
|
||||||
{
|
{
|
||||||
self->status = PGRES_FIELDS_OK;
|
self->status = PGRES_FIELDS_OK;
|
||||||
@ -275,7 +294,6 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
|
|
||||||
self->inTuples = TRUE;
|
self->inTuples = TRUE;
|
||||||
|
|
||||||
|
|
||||||
/* Force a read to occur in next_tuple */
|
/* Force a read to occur in next_tuple */
|
||||||
self->fcount = tuple_size + 1;
|
self->fcount = tuple_size + 1;
|
||||||
self->fetch_count = tuple_size + 1;
|
self->fetch_count = tuple_size + 1;
|
||||||
@ -285,9 +303,10 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
/* Always have to read the field attributes. */
|
* Always have to read the field attributes.
|
||||||
/* But we dont have to reallocate memory for them! */
|
* But we dont have to reallocate memory for them!
|
||||||
|
*/
|
||||||
|
|
||||||
if (!CI_read_fields(NULL, self->conn))
|
if (!CI_read_fields(NULL, self->conn))
|
||||||
{
|
{
|
||||||
@ -299,8 +318,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the cursor and end the transaction (if no cursors left) */
|
|
||||||
/* We only close cursor/end the transaction if a cursor was used. */
|
/*
|
||||||
|
* Close the cursor and end the transaction (if no cursors left)
|
||||||
|
* We only close cursor/end the transaction if a cursor was used.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
QR_close(QResultClass *self)
|
QR_close(QResultClass *self)
|
||||||
{
|
{
|
||||||
@ -346,12 +368,12 @@ QR_close(QResultClass *self)
|
|||||||
}
|
}
|
||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function is called by fetch_tuples() AND SQLFetch() */
|
/* This function is called by fetch_tuples() AND SQLFetch() */
|
||||||
int
|
int
|
||||||
QR_next_tuple(QResultClass *self)
|
QR_next_tuple(QResultClass *self)
|
||||||
@ -370,30 +392,31 @@ QR_next_tuple(QResultClass *self)
|
|||||||
TupleField *the_tuples = self->backend_tuples;
|
TupleField *the_tuples = self->backend_tuples;
|
||||||
/* ERROR_MSG_LENGTH is sufficient */
|
/* ERROR_MSG_LENGTH is sufficient */
|
||||||
static char msgbuffer[ERROR_MSG_LENGTH + 1];
|
static char msgbuffer[ERROR_MSG_LENGTH + 1];
|
||||||
char cmdbuffer[ERROR_MSG_LENGTH + 1]; /* QR_set_command() dups
|
/* QR_set_command() dups this string so doesn't need static */
|
||||||
* this string so dont
|
char cmdbuffer[ERROR_MSG_LENGTH + 1];
|
||||||
* need static */
|
|
||||||
char fetch[128];
|
char fetch[128];
|
||||||
QueryInfo qi;
|
QueryInfo qi;
|
||||||
|
|
||||||
if (fetch_count < fcount)
|
if (fetch_count < fcount)
|
||||||
{ /* return a row from cache */
|
{
|
||||||
|
/* return a row from cache */
|
||||||
mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount);
|
mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, fcount);
|
||||||
self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */
|
self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */
|
||||||
self->fetch_count++;
|
self->fetch_count++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (self->fcount < self->cache_size)
|
else if (self->fcount < self->cache_size)
|
||||||
{ /* last row from cache */
|
{
|
||||||
|
/* last row from cache */
|
||||||
/* We are done because we didn't even get CACHE_SIZE tuples */
|
/* We are done because we didn't even get CACHE_SIZE tuples */
|
||||||
mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
|
mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", fcount, fetch_count);
|
||||||
self->tupleField = NULL;
|
self->tupleField = NULL;
|
||||||
self->status = PGRES_END_TUPLES;
|
self->status = PGRES_END_TUPLES;
|
||||||
return -1; /* end of tuples */
|
/* end of tuples */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we need to fetch another group of rows. We may be being
|
* See if we need to fetch another group of rows. We may be being
|
||||||
* called from send_query(), and if so, don't send another fetch,
|
* called from send_query(), and if so, don't send another fetch,
|
||||||
@ -403,7 +426,6 @@ QR_next_tuple(QResultClass *self)
|
|||||||
|
|
||||||
if (!self->inTuples)
|
if (!self->inTuples)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!globals.use_declarefetch)
|
if (!globals.use_declarefetch)
|
||||||
{
|
{
|
||||||
mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
|
mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", fcount, fetch_count);
|
||||||
@ -413,8 +435,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (self->base == fcount)
|
if (self->base == fcount)
|
||||||
{ /* not a correction */
|
{
|
||||||
|
/* not a correction */
|
||||||
/* Determine the optimum cache size. */
|
/* Determine the optimum cache size. */
|
||||||
if (globals.fetch_max % self->rowset_size == 0)
|
if (globals.fetch_max % self->rowset_size == 0)
|
||||||
fetch_size = globals.fetch_max;
|
fetch_size = globals.fetch_max;
|
||||||
@ -427,8 +449,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
self->fetch_count = 1;
|
self->fetch_count = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* need to correct */
|
{
|
||||||
|
/* need to correct */
|
||||||
corrected = TRUE;
|
corrected = TRUE;
|
||||||
|
|
||||||
fetch_size = end_tuple - fcount;
|
fetch_size = end_tuple - fcount;
|
||||||
@ -437,10 +459,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
|
|
||||||
offset = self->fetch_count;
|
offset = self->fetch_count;
|
||||||
self->fetch_count++;
|
self->fetch_count++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
|
self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
|
||||||
if (!self->backend_tuples)
|
if (!self->backend_tuples)
|
||||||
{
|
{
|
||||||
@ -484,17 +504,16 @@ QR_next_tuple(QResultClass *self)
|
|||||||
self->fcount = 0;
|
self->fcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sock = CC_get_socket(self->conn);
|
sock = CC_get_socket(self->conn);
|
||||||
self->tupleField = NULL;
|
self->tupleField = NULL;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|
||||||
id = SOCK_get_char(sock);
|
id = SOCK_get_char(sock);
|
||||||
|
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
|
|
||||||
case 'T': /* Tuples within tuples cannot be handled */
|
case 'T': /* Tuples within tuples cannot be handled */
|
||||||
self->status = PGRES_BAD_RESPONSE;
|
self->status = PGRES_BAD_RESPONSE;
|
||||||
QR_set_message(self, "Tuples within tuples cannot be handled");
|
QR_set_message(self, "Tuples within tuples cannot be handled");
|
||||||
@ -523,11 +542,9 @@ QR_next_tuple(QResultClass *self)
|
|||||||
QR_set_message(self, "Error reading the tuple");
|
QR_set_message(self, "Error reading the tuple");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->fcount++;
|
self->fcount++;
|
||||||
break; /* continue reading */
|
break; /* continue reading */
|
||||||
|
|
||||||
|
|
||||||
case 'C': /* End of tuple list */
|
case 'C': /* End of tuple list */
|
||||||
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
||||||
QR_set_command(self, cmdbuffer);
|
QR_set_command(self, cmdbuffer);
|
||||||
@ -537,7 +554,6 @@ QR_next_tuple(QResultClass *self)
|
|||||||
self->inTuples = FALSE;
|
self->inTuples = FALSE;
|
||||||
if (self->fcount > 0)
|
if (self->fcount > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
qlog(" [ fetched %d rows ]\n", self->fcount);
|
qlog(" [ fetched %d rows ]\n", self->fcount);
|
||||||
mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);
|
mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->fcount);
|
||||||
|
|
||||||
@ -546,8 +562,8 @@ QR_next_tuple(QResultClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* We are surely done here (we read 0
|
{
|
||||||
* tuples) */
|
/* We are surely done here (we read 0 tuples) */
|
||||||
qlog(" [ fetched 0 rows ]\n");
|
qlog(" [ fetched 0 rows ]\n");
|
||||||
mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
|
mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
|
||||||
return -1; /* end of tuples */
|
return -1; /* end of tuples */
|
||||||
@ -585,6 +601,7 @@ QR_next_tuple(QResultClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
QR_read_tuple(QResultClass *self, char binary)
|
QR_read_tuple(QResultClass *self, char binary)
|
||||||
{
|
{
|
||||||
@ -601,7 +618,6 @@ QR_read_tuple(QResultClass *self, char binary)
|
|||||||
SocketClass *sock = CC_get_socket(self->conn);
|
SocketClass *sock = CC_get_socket(self->conn);
|
||||||
ColumnInfoClass *flds;
|
ColumnInfoClass *flds;
|
||||||
|
|
||||||
|
|
||||||
/* set the current row to read the fields into */
|
/* set the current row to read the fields into */
|
||||||
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
|
this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
|
||||||
|
|
||||||
@ -630,7 +646,6 @@ QR_read_tuple(QResultClass *self, char binary)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NO, the field is not null. so get at first the length of
|
* NO, the field is not null. so get at first the length of
|
||||||
* the field (four bytes)
|
* the field (four bytes)
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
/* Module: results.c
|
/*-------
|
||||||
|
* Module: results.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions related to
|
* Description: This module contains functions related to
|
||||||
* retrieving result information through the ODBC API.
|
* retrieving result information through the ODBC API.
|
||||||
*
|
*
|
||||||
* Classes: n/a
|
* Classes: n/a
|
||||||
*
|
*
|
||||||
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, SQLColAttributes,
|
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
|
||||||
* SQLGetData, SQLFetch, SQLExtendedFetch,
|
* SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
|
||||||
* SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
|
* SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
|
||||||
* SQLSetCursorName, SQLGetCursorName
|
* SQLSetCursorName, SQLGetCursorName
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -42,7 +43,6 @@
|
|||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLRowCount(
|
SQLRowCount(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -81,7 +81,6 @@ SQLRowCount(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
res = SC_get_Result(stmt);
|
res = SC_get_Result(stmt);
|
||||||
if (res && pcrow)
|
if (res && pcrow)
|
||||||
{
|
{
|
||||||
@ -97,7 +96,6 @@ SQLRowCount(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
*pcrow = -1;
|
*pcrow = -1;
|
||||||
|
|
||||||
mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow);
|
mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,10 +108,10 @@ SQLRowCount(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This returns the number of columns associated with the database */
|
/*
|
||||||
/* attached to "hstmt". */
|
* This returns the number of columns associated with the database
|
||||||
|
* attached to "hstmt".
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLNumResultCols(
|
SQLNumResultCols(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -135,7 +133,6 @@ SQLNumResultCols(
|
|||||||
parse_ok = FALSE;
|
parse_ok = FALSE;
|
||||||
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stmt->parse_status == STMT_PARSE_NONE)
|
if (stmt->parse_status == STMT_PARSE_NONE)
|
||||||
{
|
{
|
||||||
mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
|
mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
|
||||||
@ -152,7 +149,6 @@ SQLNumResultCols(
|
|||||||
|
|
||||||
if (!parse_ok)
|
if (!parse_ok)
|
||||||
{
|
{
|
||||||
|
|
||||||
SC_pre_execute(stmt);
|
SC_pre_execute(stmt);
|
||||||
result = SC_get_Result(stmt);
|
result = SC_get_Result(stmt);
|
||||||
|
|
||||||
@ -173,12 +169,10 @@ SQLNumResultCols(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - */
|
/*
|
||||||
|
* Return information about the database column the user wants
|
||||||
|
* information about.
|
||||||
|
*/
|
||||||
/* Return information about the database column the user wants */
|
|
||||||
/* information about. */
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLDescribeCol(
|
SQLDescribeCol(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -205,7 +199,6 @@ SQLDescribeCol(
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
RETCODE result;
|
RETCODE result;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
if (!stmt)
|
if (!stmt)
|
||||||
@ -225,23 +218,19 @@ SQLDescribeCol(
|
|||||||
|
|
||||||
icol--; /* use zero based column numbers */
|
icol--; /* use zero based column numbers */
|
||||||
|
|
||||||
|
|
||||||
parse_ok = FALSE;
|
parse_ok = FALSE;
|
||||||
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stmt->parse_status == STMT_PARSE_NONE)
|
if (stmt->parse_status == STMT_PARSE_NONE)
|
||||||
{
|
{
|
||||||
mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
|
mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt);
|
||||||
parse_statement(stmt);
|
parse_statement(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi);
|
mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi);
|
||||||
|
|
||||||
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
|
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
|
||||||
{
|
{
|
||||||
|
|
||||||
if (icol >= stmt->nfld)
|
if (icol >= stmt->nfld)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
@ -261,7 +250,6 @@ SQLDescribeCol(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If couldn't parse it OR the field being described was not parsed
|
* If couldn't parse it OR the field being described was not parsed
|
||||||
* (i.e., because it was a function or expression, etc, then do it the
|
* (i.e., because it was a function or expression, etc, then do it the
|
||||||
@ -295,20 +283,19 @@ SQLDescribeCol(
|
|||||||
col_name = QR_get_fieldname(res, icol);
|
col_name = QR_get_fieldname(res, icol);
|
||||||
fieldtype = QR_get_field_type(res, icol);
|
fieldtype = QR_get_field_type(res, icol);
|
||||||
|
|
||||||
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); /* atoi(ci->unknown_sizes
|
/* atoi(ci->unknown_sizes) */
|
||||||
* ) */
|
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
|
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
|
||||||
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
|
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
|
||||||
mylog("describeCol: col %d precision = %d\n", icol, precision);
|
mylog("describeCol: col %d precision = %d\n", icol, precision);
|
||||||
|
|
||||||
|
|
||||||
result = SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
|
|
||||||
/************************/
|
/*
|
||||||
/* COLUMN NAME */
|
* COLUMN NAME
|
||||||
/************************/
|
*/
|
||||||
len = strlen(col_name);
|
len = strlen(col_name);
|
||||||
|
|
||||||
if (pcbColName)
|
if (pcbColName)
|
||||||
@ -326,10 +313,9 @@ SQLDescribeCol(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/************************/
|
* SQL TYPE
|
||||||
/* SQL TYPE */
|
*/
|
||||||
/************************/
|
|
||||||
if (pfSqlType)
|
if (pfSqlType)
|
||||||
{
|
{
|
||||||
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
||||||
@ -337,12 +323,11 @@ SQLDescribeCol(
|
|||||||
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************/
|
/*
|
||||||
/* PRECISION */
|
* PRECISION
|
||||||
/************************/
|
*/
|
||||||
if (pcbColDef)
|
if (pcbColDef)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (precision < 0)
|
if (precision < 0)
|
||||||
precision = 0; /* "I dont know" */
|
precision = 0; /* "I dont know" */
|
||||||
|
|
||||||
@ -351,9 +336,9 @@ SQLDescribeCol(
|
|||||||
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************/
|
/*
|
||||||
/* SCALE */
|
* SCALE
|
||||||
/************************/
|
*/
|
||||||
if (pibScale)
|
if (pibScale)
|
||||||
{
|
{
|
||||||
Int2 scale;
|
Int2 scale;
|
||||||
@ -366,9 +351,9 @@ SQLDescribeCol(
|
|||||||
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************/
|
/*
|
||||||
/* NULLABILITY */
|
* NULLABILITY
|
||||||
/************************/
|
*/
|
||||||
if (pfNullable)
|
if (pfNullable)
|
||||||
{
|
{
|
||||||
*pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
|
*pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
|
||||||
@ -379,8 +364,8 @@ SQLDescribeCol(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns result column descriptor information for a result set. */
|
|
||||||
|
|
||||||
|
/* Returns result column descriptor information for a result set. */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLColAttributes(
|
SQLColAttributes(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -421,16 +406,16 @@ SQLColAttributes(
|
|||||||
|
|
||||||
icol--;
|
icol--;
|
||||||
|
|
||||||
unknown_sizes = globals.unknown_sizes; /* atoi(ci->unknown_sizes);
|
/* atoi(ci->unknown_sizes); */
|
||||||
* */
|
unknown_sizes = globals.unknown_sizes;
|
||||||
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) /* not appropriate for
|
|
||||||
* SQLColAttributes() */
|
/* not appropriate for SQLColAttributes() */
|
||||||
|
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW)
|
||||||
unknown_sizes = UNKNOWNS_AS_MAX;
|
unknown_sizes = UNKNOWNS_AS_MAX;
|
||||||
|
|
||||||
parse_ok = FALSE;
|
parse_ok = FALSE;
|
||||||
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stmt->parse_status == STMT_PARSE_NONE)
|
if (stmt->parse_status == STMT_PARSE_NONE)
|
||||||
{
|
{
|
||||||
mylog("SQLColAttributes: calling parse_statement\n");
|
mylog("SQLColAttributes: calling parse_statement\n");
|
||||||
@ -453,7 +438,6 @@ SQLColAttributes(
|
|||||||
|
|
||||||
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
|
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
|
||||||
{
|
{
|
||||||
|
|
||||||
if (icol >= cols)
|
if (icol >= cols)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
@ -461,7 +445,6 @@ SQLColAttributes(
|
|||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
field_type = stmt->fi[icol]->type;
|
field_type = stmt->fi[icol]->type;
|
||||||
if (field_type > 0)
|
if (field_type > 0)
|
||||||
parse_ok = TRUE;
|
parse_ok = TRUE;
|
||||||
@ -527,7 +510,6 @@ SQLColAttributes(
|
|||||||
*
|
*
|
||||||
* case SQL_COLUMN_COUNT:
|
* case SQL_COLUMN_COUNT:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case SQL_COLUMN_DISPLAY_SIZE:
|
case SQL_COLUMN_DISPLAY_SIZE:
|
||||||
value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
||||||
|
|
||||||
@ -543,11 +525,10 @@ SQLColAttributes(
|
|||||||
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
|
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} /* otherwise same as column name -- FALL
|
}
|
||||||
* THROUGH!!! */
|
/* otherwise same as column name -- FALL THROUGH!!! */
|
||||||
|
|
||||||
case SQL_COLUMN_NAME:
|
case SQL_COLUMN_NAME:
|
||||||
|
|
||||||
p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);
|
p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);
|
||||||
|
|
||||||
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
|
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
|
||||||
@ -590,7 +571,6 @@ SQLColAttributes(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TABLE_NAME:
|
case SQL_COLUMN_TABLE_NAME:
|
||||||
|
|
||||||
p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
|
p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
|
||||||
|
|
||||||
mylog("SQLColAttr: TABLE_NAME = '%s'\n", p);
|
mylog("SQLColAttr: TABLE_NAME = '%s'\n", p);
|
||||||
@ -612,14 +592,12 @@ SQLColAttributes(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_UPDATABLE:
|
case SQL_COLUMN_UPDATABLE:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Neither Access or Borland care about this.
|
* Neither Access or Borland care about this.
|
||||||
*
|
*
|
||||||
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
|
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
|
||||||
* else
|
* else
|
||||||
*/
|
*/
|
||||||
|
|
||||||
value = SQL_ATTR_WRITE;
|
value = SQL_ATTR_WRITE;
|
||||||
|
|
||||||
mylog("SQLColAttr: UPDATEABLE = %d\n", value);
|
mylog("SQLColAttr: UPDATEABLE = %d\n", value);
|
||||||
@ -648,19 +626,17 @@ SQLColAttributes(
|
|||||||
*pcbDesc = len;
|
*pcbDesc = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* numeric data */
|
{
|
||||||
|
/* numeric data */
|
||||||
if (pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = value;
|
*pfDesc = value;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns result data for a single column in the current row. */
|
|
||||||
|
|
||||||
|
/* Returns result data for a single column in the current row. */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetData(
|
SQLGetData(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -707,7 +683,6 @@ SQLGetData(
|
|||||||
|
|
||||||
if (icol == 0)
|
if (icol == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (stmt->options.use_bookmarks == SQL_UB_OFF)
|
if (stmt->options.use_bookmarks == SQL_UB_OFF)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_COLNUM_ERROR;
|
stmt->errornumber = STMT_COLNUM_ERROR;
|
||||||
@ -726,12 +701,9 @@ SQLGetData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_bookmark = TRUE;
|
get_bookmark = TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/* use zero-based column numbers */
|
/* use zero-based column numbers */
|
||||||
icol--;
|
icol--;
|
||||||
|
|
||||||
@ -770,7 +742,8 @@ SQLGetData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* it's a SOCKET result (backend data) */
|
{
|
||||||
|
/* it's a SOCKET result (backend data) */
|
||||||
if (stmt->currTuple == -1 || !res || !res->tupleField)
|
if (stmt->currTuple == -1 || !res || !res->tupleField)
|
||||||
{
|
{
|
||||||
stmt->errormsg = "Not positioned on a valid row for GetData.";
|
stmt->errormsg = "Not positioned on a valid row for GetData.";
|
||||||
@ -845,10 +818,10 @@ SQLGetData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/* Returns data for bound columns in the current row ("hstmt->iCursor"), */
|
* Returns data for bound columns in the current row ("hstmt->iCursor"),
|
||||||
/* advances the cursor. */
|
* advances the cursor.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLFetch(
|
SQLFetch(
|
||||||
HSTMT hstmt)
|
HSTMT hstmt)
|
||||||
@ -892,7 +865,6 @@ SQLFetch(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (stmt->status != STMT_FINISHED)
|
if (stmt->status != STMT_FINISHED)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_STATUS_ERROR;
|
stmt->errornumber = STMT_STATUS_ERROR;
|
||||||
@ -917,8 +889,8 @@ SQLFetch(
|
|||||||
return SC_fetch(stmt);
|
return SC_fetch(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This fetchs a block of data (rowset). */
|
|
||||||
|
|
||||||
|
/* This fetchs a block of data (rowset). */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLExtendedFetch(
|
SQLExtendedFetch(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1020,7 +992,6 @@ SQLExtendedFetch(
|
|||||||
switch (fFetchType)
|
switch (fFetchType)
|
||||||
{
|
{
|
||||||
case SQL_FETCH_NEXT:
|
case SQL_FETCH_NEXT:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From the odbc spec... If positioned before the start of the
|
* From the odbc spec... If positioned before the start of the
|
||||||
* RESULT SET, then this should be equivalent to
|
* RESULT SET, then this should be equivalent to
|
||||||
@ -1031,36 +1002,25 @@ SQLExtendedFetch(
|
|||||||
stmt->rowset_start = 0;
|
stmt->rowset_start = 0;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
|
|
||||||
stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
|
stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
|
||||||
}
|
|
||||||
|
|
||||||
mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
|
mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_FETCH_PRIOR:
|
case SQL_FETCH_PRIOR:
|
||||||
mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
|
mylog("SQL_FETCH_PRIOR: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From the odbc spec... If positioned after the end of the
|
* From the odbc spec... If positioned after the end of the
|
||||||
* RESULT SET, then this should be equivalent to
|
* RESULT SET, then this should be equivalent to
|
||||||
* SQL_FETCH_LAST.
|
* SQL_FETCH_LAST.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (stmt->rowset_start >= num_tuples)
|
if (stmt->rowset_start >= num_tuples)
|
||||||
{
|
{
|
||||||
stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
|
stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
|
|
||||||
stmt->rowset_start -= stmt->options.rowset_size;
|
stmt->rowset_start -= stmt->options.rowset_size;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_FETCH_FIRST:
|
case SQL_FETCH_FIRST:
|
||||||
@ -1091,11 +1051,9 @@ SQLExtendedFetch(
|
|||||||
/* Position with respect to the end of the result set */
|
/* Position with respect to the end of the result set */
|
||||||
else
|
else
|
||||||
stmt->rowset_start = num_tuples + irow;
|
stmt->rowset_start = num_tuples + irow;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_FETCH_RELATIVE:
|
case SQL_FETCH_RELATIVE:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Refresh the current rowset -- not currently implemented,
|
* Refresh the current rowset -- not currently implemented,
|
||||||
* but lie anyway
|
* but lie anyway
|
||||||
@ -1104,25 +1062,20 @@ SQLExtendedFetch(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
stmt->rowset_start += irow;
|
stmt->rowset_start += irow;
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_FETCH_BOOKMARK:
|
case SQL_FETCH_BOOKMARK:
|
||||||
|
|
||||||
stmt->rowset_start = irow - 1;
|
stmt->rowset_start = irow - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
|
SC_log_error(func, "Unsupported SQLExtendedFetch Direction", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/***********************************/
|
* CHECK FOR PROPER CURSOR STATE
|
||||||
/* CHECK FOR PROPER CURSOR STATE */
|
*/
|
||||||
/***********************************/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle Declare Fetch style specially because the end is not really
|
* Handle Declare Fetch style specially because the end is not really
|
||||||
@ -1172,7 +1125,6 @@ SQLExtendedFetch(
|
|||||||
truncated = error = FALSE;
|
truncated = error = FALSE;
|
||||||
for (i = 0; i < stmt->options.rowset_size; i++)
|
for (i = 0; i < stmt->options.rowset_size; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
stmt->bind_row = i; /* set the binding location */
|
stmt->bind_row = i; /* set the binding location */
|
||||||
result = SC_fetch(stmt);
|
result = SC_fetch(stmt);
|
||||||
|
|
||||||
@ -1212,21 +1164,21 @@ SQLExtendedFetch(
|
|||||||
*pcrow = i;
|
*pcrow = i;
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return SQL_NO_DATA_FOUND; /* Only DeclareFetch should wind
|
/* Only DeclareFetch should wind up here */
|
||||||
* up here */
|
return SQL_NO_DATA_FOUND;
|
||||||
else if (error)
|
else if (error)
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
else if (truncated)
|
else if (truncated)
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
else
|
else
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This determines whether there are more results sets available for */
|
/*
|
||||||
/* the "hstmt". */
|
* This determines whether there are more results sets available for
|
||||||
|
* the "hstmt".
|
||||||
|
*/
|
||||||
/* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
|
/* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLMoreResults(
|
SQLMoreResults(
|
||||||
@ -1235,8 +1187,11 @@ SQLMoreResults(
|
|||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch. */
|
|
||||||
/* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch. */
|
/*
|
||||||
|
* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch.
|
||||||
|
* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch.
|
||||||
|
*/
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetPos(
|
SQLSetPos(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1301,11 +1256,10 @@ SQLSetPos(
|
|||||||
stmt->currTuple = stmt->rowset_start + irow;
|
stmt->currTuple = stmt->rowset_start + irow;
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets options that control the behavior of cursors. */
|
|
||||||
|
|
||||||
|
/* Sets options that control the behavior of cursors. */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetScrollOptions(
|
SQLSetScrollOptions(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1321,7 +1275,6 @@ SQLSetScrollOptions(
|
|||||||
|
|
||||||
|
|
||||||
/* Set the cursor name on a statement handle */
|
/* Set the cursor name on a statement handle */
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLSetCursorName(
|
SQLSetCursorName(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -1354,8 +1307,8 @@ SQLSetCursorName(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the cursor name for a statement handle */
|
|
||||||
|
|
||||||
|
/* Return the cursor name for a statement handle */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
SQLGetCursorName(
|
SQLGetCursorName(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: setup.c
|
/*-------
|
||||||
|
* Module: setup.c
|
||||||
*
|
*
|
||||||
* Description: This module contains the setup functions for
|
* Description: This module contains the setup functions for
|
||||||
* adding/modifying a Data Source in the ODBC.INI portion
|
* adding/modifying a Data Source in the ODBC.INI portion
|
||||||
@ -9,7 +10,7 @@
|
|||||||
* API functions: ConfigDSN
|
* API functions: ConfigDSN
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
@ -28,7 +29,7 @@
|
|||||||
extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
|
extern HINSTANCE NEAR s_hModule;/* Saved module handle. */
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
/* Constants --------------------------------------------------------------- */
|
/* Constants */
|
||||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -40,7 +41,7 @@ extern GLOBAL_VALUES globals;
|
|||||||
#define MAXDSNAME (32+1) /* Max data source name length */
|
#define MAXDSNAME (32+1) /* Max data source name length */
|
||||||
|
|
||||||
|
|
||||||
/* Globals ----------------------------------------------------------------- */
|
/* Globals */
|
||||||
/* NOTE: All these are used by the dialog procedures */
|
/* NOTE: All these are used by the dialog procedures */
|
||||||
typedef struct tagSETUPDLG
|
typedef struct tagSETUPDLG
|
||||||
{
|
{
|
||||||
@ -55,24 +56,26 @@ typedef struct tagSETUPDLG
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes -------------------------------------------------------------- */
|
/* Prototypes */
|
||||||
void INTFUNC CenterDialog(HWND hdlg);
|
void INTFUNC CenterDialog(HWND hdlg);
|
||||||
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
|
int CALLBACK ConfigDlgProc(HWND hdlg, WORD wMsg, WPARAM wParam, LPARAM lParam);
|
||||||
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
|
void INTFUNC ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg);
|
||||||
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
|
BOOL INTFUNC SetDSNAttributes(HWND hwnd, LPSETUPDLG lpsetupdlg);
|
||||||
|
|
||||||
|
|
||||||
/* ConfigDSN ---------------------------------------------------------------
|
/*--------
|
||||||
Description: ODBC Setup entry point
|
* ConfigDSN
|
||||||
This entry point is called by the ODBC Installer
|
*
|
||||||
(see file header for more details)
|
* Description: ODBC Setup entry point
|
||||||
Input : hwnd ----------- Parent window handle
|
* This entry point is called by the ODBC Installer
|
||||||
fRequest ------- Request type (i.e., add, config, or remove)
|
* (see file header for more details)
|
||||||
lpszDriver ----- Driver name
|
* Input : hwnd ----------- Parent window handle
|
||||||
lpszAttributes - data source attribute string
|
* fRequest ------- Request type (i.e., add, config, or remove)
|
||||||
Output : TRUE success, FALSE otherwise
|
* lpszDriver ----- Driver name
|
||||||
--------------------------------------------------------------------------*/
|
* lpszAttributes - data source attribute string
|
||||||
|
* Output : TRUE success, FALSE otherwise
|
||||||
|
*--------
|
||||||
|
*/
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
ConfigDSN(HWND hwnd,
|
ConfigDSN(HWND hwnd,
|
||||||
WORD fRequest,
|
WORD fRequest,
|
||||||
@ -111,7 +114,6 @@ ConfigDSN(HWND hwnd,
|
|||||||
else
|
else
|
||||||
fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn);
|
fSuccess = SQLRemoveDSNFromIni(lpsetupdlg->ci.dsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add or Configure data source */
|
/* Add or Configure data source */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -134,7 +136,6 @@ ConfigDSN(HWND hwnd,
|
|||||||
ConfigDlgProc,
|
ConfigDlgProc,
|
||||||
(LONG) (LPSTR) lpsetupdlg));
|
(LONG) (LPSTR) lpsetupdlg));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (lpsetupdlg->ci.dsn[0])
|
else if (lpsetupdlg->ci.dsn[0])
|
||||||
fSuccess = SetDSNAttributes(hwnd, lpsetupdlg);
|
fSuccess = SetDSNAttributes(hwnd, lpsetupdlg);
|
||||||
else
|
else
|
||||||
@ -148,11 +149,14 @@ ConfigDSN(HWND hwnd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* CenterDialog ------------------------------------------------------------
|
/*-------
|
||||||
Description: Center the dialog over the frame window
|
* CenterDialog
|
||||||
Input : hdlg -- Dialog window handle
|
*
|
||||||
Output : None
|
* Description: Center the dialog over the frame window
|
||||||
--------------------------------------------------------------------------*/
|
* Input : hdlg -- Dialog window handle
|
||||||
|
* Output : None
|
||||||
|
*-------
|
||||||
|
*/
|
||||||
void INTFUNC
|
void INTFUNC
|
||||||
CenterDialog(HWND hdlg)
|
CenterDialog(HWND hdlg)
|
||||||
{
|
{
|
||||||
@ -198,23 +202,22 @@ CenterDialog(HWND hdlg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ConfigDlgProc -----------------------------------------------------------
|
/*-------
|
||||||
Description: Manage add data source name dialog
|
* ConfigDlgProc
|
||||||
Input : hdlg --- Dialog window handle
|
* Description: Manage add data source name dialog
|
||||||
wMsg --- Message
|
* Input : hdlg --- Dialog window handle
|
||||||
wParam - Message parameter
|
* wMsg --- Message
|
||||||
lParam - Message parameter
|
* wParam - Message parameter
|
||||||
Output : TRUE if message processed, FALSE otherwise
|
* lParam - Message parameter
|
||||||
--------------------------------------------------------------------------*/
|
* Output : TRUE if message processed, FALSE otherwise
|
||||||
|
*-------
|
||||||
|
*/
|
||||||
int CALLBACK
|
int CALLBACK
|
||||||
ConfigDlgProc(HWND hdlg,
|
ConfigDlgProc(HWND hdlg,
|
||||||
WORD wMsg,
|
WORD wMsg,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
LPARAM lParam)
|
LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (wMsg)
|
switch (wMsg)
|
||||||
{
|
{
|
||||||
/* Initialize the dialog */
|
/* Initialize the dialog */
|
||||||
@ -241,11 +244,9 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
/* Fill in any defaults */
|
/* Fill in any defaults */
|
||||||
getDSNdefaults(ci);
|
getDSNdefaults(ci);
|
||||||
|
|
||||||
|
|
||||||
/* Initialize dialog fields */
|
/* Initialize dialog fields */
|
||||||
SetDlgStuff(hdlg, ci);
|
SetDlgStuff(hdlg, ci);
|
||||||
|
|
||||||
|
|
||||||
if (lpsetupdlg->fDefault)
|
if (lpsetupdlg->fDefault)
|
||||||
{
|
{
|
||||||
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
|
EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
|
||||||
@ -260,13 +261,10 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
return TRUE; /* Focus was not set */
|
return TRUE; /* Focus was not set */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Process buttons */
|
/* Process buttons */
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
|
|
||||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure the OK button is enabled only when a data
|
* Ensure the OK button is enabled only when a data
|
||||||
* source name
|
* source name
|
||||||
@ -281,7 +279,6 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
EnableWindow(GetDlgItem(hdlg, IDOK),
|
EnableWindow(GetDlgItem(hdlg, IDOK),
|
||||||
GetDlgItemText(hdlg, IDC_DSNAME,
|
GetDlgItemText(hdlg, IDC_DSNAME,
|
||||||
szItem, sizeof(szItem)));
|
szItem, sizeof(szItem)));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -297,8 +294,6 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
GetDlgItemText(hdlg, IDC_DSNAME,
|
GetDlgItemText(hdlg, IDC_DSNAME,
|
||||||
lpsetupdlg->ci.dsn,
|
lpsetupdlg->ci.dsn,
|
||||||
sizeof(lpsetupdlg->ci.dsn));
|
sizeof(lpsetupdlg->ci.dsn));
|
||||||
|
|
||||||
|
|
||||||
/* Get Dialog Values */
|
/* Get Dialog Values */
|
||||||
GetDlgStuff(hdlg, &lpsetupdlg->ci);
|
GetDlgStuff(hdlg, &lpsetupdlg->ci);
|
||||||
|
|
||||||
@ -312,7 +307,6 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case IDC_DRIVER:
|
case IDC_DRIVER:
|
||||||
|
|
||||||
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
|
DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
|
||||||
hdlg, driver_optionsProc, (LPARAM) NULL);
|
hdlg, driver_optionsProc, (LPARAM) NULL);
|
||||||
|
|
||||||
@ -330,7 +324,6 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,11 +332,14 @@ ConfigDlgProc(HWND hdlg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ParseAttributes ---------------------------------------------------------
|
/*-------
|
||||||
Description: Parse attribute string moving values into the aAttr array
|
* ParseAttributes
|
||||||
Input : lpszAttributes - Pointer to attribute string
|
*
|
||||||
Output : None (global aAttr normally updated)
|
* Description: Parse attribute string moving values into the aAttr array
|
||||||
--------------------------------------------------------------------------*/
|
* Input : lpszAttributes - Pointer to attribute string
|
||||||
|
* Output : None (global aAttr normally updated)
|
||||||
|
*-------
|
||||||
|
*/
|
||||||
void INTFUNC
|
void INTFUNC
|
||||||
ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
||||||
{
|
{
|
||||||
@ -356,8 +352,8 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
|||||||
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
|
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
|
||||||
|
|
||||||
for (lpsz = lpszAttributes; *lpsz; lpsz++)
|
for (lpsz = lpszAttributes; *lpsz; lpsz++)
|
||||||
{ /* Extract key name (e.g., DSN), it must
|
{
|
||||||
* be terminated by an equals */
|
/* Extract key name (e.g., DSN), it must be terminated by an equals */
|
||||||
lpszStart = lpsz;
|
lpszStart = lpsz;
|
||||||
for (;; lpsz++)
|
for (;; lpsz++)
|
||||||
{
|
{
|
||||||
@ -370,15 +366,14 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
|||||||
cbKey = lpsz - lpszStart;
|
cbKey = lpsz - lpszStart;
|
||||||
if (cbKey < sizeof(aszKey))
|
if (cbKey < sizeof(aszKey))
|
||||||
{
|
{
|
||||||
|
|
||||||
_fmemcpy(aszKey, lpszStart, cbKey);
|
_fmemcpy(aszKey, lpszStart, cbKey);
|
||||||
aszKey[cbKey] = '\0';
|
aszKey[cbKey] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate end of key value */
|
/* Locate end of key value */
|
||||||
lpszStart = ++lpsz;
|
lpszStart = ++lpsz;
|
||||||
for (; *lpsz; lpsz++);
|
for (; *lpsz; lpsz++)
|
||||||
|
;
|
||||||
|
|
||||||
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
|
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
|
||||||
_fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
|
_fmemcpy(value, lpszStart, MIN(lpsz - lpszStart + 1, MAXPGPATH));
|
||||||
@ -392,12 +387,14 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SetDSNAttributes --------------------------------------------------------
|
/*--------
|
||||||
Description: Write data source attributes to ODBC.INI
|
* SetDSNAttributes
|
||||||
Input : hwnd - Parent window handle (plus globals)
|
*
|
||||||
Output : TRUE if successful, FALSE otherwise
|
* Description: Write data source attributes to ODBC.INI
|
||||||
--------------------------------------------------------------------------*/
|
* Input : hwnd - Parent window handle (plus globals)
|
||||||
|
* Output : TRUE if successful, FALSE otherwise
|
||||||
|
*--------
|
||||||
|
*/
|
||||||
BOOL INTFUNC
|
BOOL INTFUNC
|
||||||
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
|
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
|
||||||
{
|
{
|
||||||
@ -425,11 +422,9 @@ SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Update ODBC.INI */
|
/* Update ODBC.INI */
|
||||||
writeDSNinfo(&lpsetupdlg->ci);
|
writeDSNinfo(&lpsetupdlg->ci);
|
||||||
|
|
||||||
|
|
||||||
/* If the data source name has changed, remove the old name */
|
/* If the data source name has changed, remove the old name */
|
||||||
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
|
if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
|
||||||
SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
|
SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: socket.c
|
/*-------
|
||||||
|
* Module: socket.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions for low level socket
|
* Description: This module contains functions for low level socket
|
||||||
* operations (connecting/reading/writing to the backend)
|
* operations (connecting/reading/writing to the backend)
|
||||||
@ -8,7 +9,7 @@
|
|||||||
* API functions: none
|
* API functions: none
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -42,6 +43,7 @@ SOCK_clear_error(SocketClass *self)
|
|||||||
self->errormsg = NULL;
|
self->errormsg = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SocketClass *
|
SocketClass *
|
||||||
SOCK_Constructor()
|
SOCK_Constructor()
|
||||||
{
|
{
|
||||||
@ -70,16 +72,14 @@ SOCK_Constructor()
|
|||||||
free(rv);
|
free(rv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv->errormsg = NULL;
|
rv->errormsg = NULL;
|
||||||
rv->errornumber = 0;
|
rv->errornumber = 0;
|
||||||
|
|
||||||
rv->reverse = FALSE;
|
rv->reverse = FALSE;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SOCK_Destructor(SocketClass *self)
|
SOCK_Destructor(SocketClass *self)
|
||||||
{
|
{
|
||||||
@ -97,7 +97,6 @@ SOCK_Destructor(SocketClass *self)
|
|||||||
free(self->buffer_out);
|
free(self->buffer_out);
|
||||||
|
|
||||||
free(self);
|
free(self);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,7 +148,6 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
|
|||||||
if (connect(self->socket, (struct sockaddr *) & (sadr),
|
if (connect(self->socket, (struct sockaddr *) & (sadr),
|
||||||
sizeof(sadr)) < 0)
|
sizeof(sadr)) < 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
self->errornumber = SOCKET_COULD_NOT_CONNECT;
|
self->errornumber = SOCKET_COULD_NOT_CONNECT;
|
||||||
self->errormsg = "Could not connect to remote socket.";
|
self->errormsg = "Could not connect to remote socket.";
|
||||||
closesocket(self->socket);
|
closesocket(self->socket);
|
||||||
@ -194,8 +192,9 @@ SOCK_put_n_char(SocketClass *self, char *buffer, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* bufsize must include room for the null terminator
|
/*
|
||||||
will read at most bufsize-1 characters + null.
|
* bufsize must include room for the null terminator
|
||||||
|
* will read at most bufsize-1 characters + null.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
|
SOCK_get_string(SocketClass *self, char *buffer, int bufsize)
|
||||||
@ -297,15 +296,16 @@ SOCK_flush_output(SocketClass *self)
|
|||||||
self->buffer_filled_out = 0;
|
self->buffer_filled_out = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char
|
unsigned char
|
||||||
SOCK_get_next_byte(SocketClass *self)
|
SOCK_get_next_byte(SocketClass *self)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (self->buffer_read_in >= self->buffer_filled_in)
|
if (self->buffer_read_in >= self->buffer_filled_in)
|
||||||
{
|
{
|
||||||
/* there are no more bytes left in the buffer so */
|
/*
|
||||||
/* reload the buffer */
|
* there are no more bytes left in the buffer so
|
||||||
|
* reload the buffer
|
||||||
|
*/
|
||||||
self->buffer_read_in = 0;
|
self->buffer_read_in = 0;
|
||||||
self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
|
self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, globals.socket_buffersize, 0);
|
||||||
|
|
||||||
@ -329,6 +329,7 @@ SOCK_get_next_byte(SocketClass *self)
|
|||||||
return self->buffer_in[self->buffer_read_in++];
|
return self->buffer_in[self->buffer_read_in++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
|
SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Module: statement.c
|
/*-------
|
||||||
|
* Module: statement.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions related to creating
|
* Description: This module contains functions related to creating
|
||||||
* and manipulating a statement.
|
* and manipulating a statement.
|
||||||
@ -8,7 +9,7 @@
|
|||||||
* API functions: SQLAllocStmt, SQLFreeStmt
|
* API functions: SQLAllocStmt, SQLFreeStmt
|
||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*-------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -44,6 +45,7 @@ extern GLOBAL_VALUES globals;
|
|||||||
#endif
|
#endif
|
||||||
#define PRN_NULLCHECK
|
#define PRN_NULLCHECK
|
||||||
|
|
||||||
|
|
||||||
/* Map sql commands to statement types */
|
/* Map sql commands to statement types */
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@ -126,12 +128,9 @@ SQLAllocStmt(HDBC hdbc,
|
|||||||
|
|
||||||
*phstmt = (HSTMT) stmt;
|
*phstmt = (HSTMT) stmt;
|
||||||
|
|
||||||
/*
|
/* Copy default statement options based from Connection options */
|
||||||
* Copy default statement options based from Connection options
|
|
||||||
*/
|
|
||||||
stmt->options = conn->stmtOptions;
|
stmt->options = conn->stmtOptions;
|
||||||
|
|
||||||
|
|
||||||
/* Save the handle for later */
|
/* Save the handle for later */
|
||||||
stmt->phstmt = phstmt;
|
stmt->phstmt = phstmt;
|
||||||
|
|
||||||
@ -180,29 +179,27 @@ SQLFreeStmt(HSTMT hstmt,
|
|||||||
|
|
||||||
/* Destroy the statement and free any results, cursors, etc. */
|
/* Destroy the statement and free any results, cursors, etc. */
|
||||||
SC_Destructor(stmt);
|
SC_Destructor(stmt);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (fOption == SQL_UNBIND)
|
else if (fOption == SQL_UNBIND)
|
||||||
{
|
{
|
||||||
SC_unbind_cols(stmt);
|
SC_unbind_cols(stmt);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (fOption == SQL_CLOSE)
|
else if (fOption == SQL_CLOSE)
|
||||||
{
|
{
|
||||||
/* this should discard all the results, but leave the statement */
|
/*
|
||||||
/* itself in place (it can be executed again) */
|
* this should discard all the results, but leave the statement
|
||||||
|
* itself in place (it can be executed again)
|
||||||
|
*/
|
||||||
if (!SC_recycle_statement(stmt))
|
if (!SC_recycle_statement(stmt))
|
||||||
{
|
{
|
||||||
/* errormsg passed in above */
|
/* errormsg passed in above */
|
||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (fOption == SQL_RESET_PARAMS)
|
else if (fOption == SQL_RESET_PARAMS)
|
||||||
{
|
{
|
||||||
SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
|
SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -216,8 +213,7 @@ SQLFreeStmt(HSTMT hstmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/**********************************************************************
|
|
||||||
* StatementClass implementation
|
* StatementClass implementation
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -234,6 +230,7 @@ InitializeStatementOptions(StatementOptions *opt)
|
|||||||
opt->use_bookmarks = SQL_UB_OFF;
|
opt->use_bookmarks = SQL_UB_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StatementClass *
|
StatementClass *
|
||||||
SC_Constructor(void)
|
SC_Constructor(void)
|
||||||
{
|
{
|
||||||
@ -288,7 +285,6 @@ SC_Constructor(void)
|
|||||||
rv->nfld = 0;
|
rv->nfld = 0;
|
||||||
rv->parse_status = STMT_PARSE_NONE;
|
rv->parse_status = STMT_PARSE_NONE;
|
||||||
|
|
||||||
|
|
||||||
/* Clear Statement Options -- defaults will be set in AllocStmt */
|
/* Clear Statement Options -- defaults will be set in AllocStmt */
|
||||||
memset(&rv->options, 0, sizeof(StatementOptions));
|
memset(&rv->options, 0, sizeof(StatementOptions));
|
||||||
|
|
||||||
@ -298,10 +294,10 @@ SC_Constructor(void)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
SC_Destructor(StatementClass *self)
|
SC_Destructor(StatementClass *self)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
|
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc);
|
||||||
if (STMT_EXECUTING == self->status)
|
if (STMT_EXECUTING == self->status)
|
||||||
{
|
{
|
||||||
@ -325,18 +321,13 @@ SC_Destructor(StatementClass *self)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* the memory pointed to by the bindings is not deallocated by the
|
* the memory pointed to by the bindings is not deallocated by the
|
||||||
* driver
|
* driver but by the application that uses that driver, so we don't have to
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* by by the application that uses that driver, so we don't have to
|
|
||||||
* care
|
* care
|
||||||
*/
|
*/
|
||||||
/* about that here. */
|
/* about that here. */
|
||||||
if (self->bindings)
|
if (self->bindings)
|
||||||
free(self->bindings);
|
free(self->bindings);
|
||||||
|
|
||||||
|
|
||||||
/* Free the parsed table information */
|
/* Free the parsed table information */
|
||||||
if (self->ti)
|
if (self->ti)
|
||||||
{
|
{
|
||||||
@ -358,7 +349,6 @@ SC_Destructor(StatementClass *self)
|
|||||||
free(self->fi);
|
free(self->fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free(self);
|
free(self);
|
||||||
|
|
||||||
mylog("SC_Destructor: EXIT\n");
|
mylog("SC_Destructor: EXIT\n");
|
||||||
@ -366,8 +356,10 @@ SC_Destructor(StatementClass *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free parameters and free the memory from the
|
|
||||||
data-at-execution parameters that was allocated in SQLPutData.
|
/*
|
||||||
|
* Free parameters and free the memory from the
|
||||||
|
* data-at-execution parameters that was allocated in SQLPutData.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SC_free_params(StatementClass *self, char option)
|
SC_free_params(StatementClass *self, char option)
|
||||||
@ -383,7 +375,6 @@ SC_free_params(StatementClass *self, char option)
|
|||||||
{
|
{
|
||||||
if (self->parameters[i].data_at_exec == TRUE)
|
if (self->parameters[i].data_at_exec == TRUE)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (self->parameters[i].EXEC_used)
|
if (self->parameters[i].EXEC_used)
|
||||||
{
|
{
|
||||||
free(self->parameters[i].EXEC_used);
|
free(self->parameters[i].EXEC_used);
|
||||||
@ -430,9 +421,10 @@ statement_type(char *statement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Called from SQLPrepare if STMT_PREMATURE, or
|
/*
|
||||||
from SQLExecute if STMT_FINISHED, or
|
* Called from SQLPrepare if STMT_PREMATURE, or
|
||||||
from SQLFreeStmt(SQL_CLOSE)
|
* from SQLExecute if STMT_FINISHED, or
|
||||||
|
* from SQLFreeStmt(SQL_CLOSE)
|
||||||
*/
|
*/
|
||||||
char
|
char
|
||||||
SC_recycle_statement(StatementClass *self)
|
SC_recycle_statement(StatementClass *self)
|
||||||
@ -472,7 +464,6 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
conn = SC_get_conn(self);
|
conn = SC_get_conn(self);
|
||||||
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
|
|
||||||
QResultClass *res = CC_send_query(conn, "ABORT", NULL);
|
QResultClass *res = CC_send_query(conn, "ABORT", NULL);
|
||||||
|
|
||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
@ -523,10 +514,9 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
}
|
}
|
||||||
self->inaccurate_result = FALSE;
|
self->inaccurate_result = FALSE;
|
||||||
|
|
||||||
/****************************************************************/
|
/*
|
||||||
/* Reset only parameters that have anything to do with results */
|
* Reset only parameters that have anything to do with results
|
||||||
/****************************************************************/
|
*/
|
||||||
|
|
||||||
self->status = STMT_READY;
|
self->status = STMT_READY;
|
||||||
self->manual_result = FALSE;/* very important */
|
self->manual_result = FALSE;/* very important */
|
||||||
|
|
||||||
@ -542,14 +532,17 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
|
|
||||||
self->lobj_fd = -1;
|
self->lobj_fd = -1;
|
||||||
|
|
||||||
/* Free any data at exec params before the statement is executed */
|
/*
|
||||||
/* again. If not, then there will be a memory leak when */
|
* Free any data at exec params before the statement is executed
|
||||||
/* the next SQLParamData/SQLPutData is called. */
|
* again. If not, then there will be a memory leak when
|
||||||
|
* the next SQLParamData/SQLPutData is called.
|
||||||
|
*/
|
||||||
SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
|
SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
|
/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
|
||||||
void
|
void
|
||||||
SC_pre_execute(StatementClass *self)
|
SC_pre_execute(StatementClass *self)
|
||||||
@ -586,6 +579,7 @@ SC_pre_execute(StatementClass *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is only called from SQLFreeStmt(SQL_UNBIND) */
|
/* This is only called from SQLFreeStmt(SQL_UNBIND) */
|
||||||
char
|
char
|
||||||
SC_unbind_cols(StatementClass *self)
|
SC_unbind_cols(StatementClass *self)
|
||||||
@ -607,6 +601,7 @@ SC_unbind_cols(StatementClass *self)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SC_clear_error(StatementClass *self)
|
SC_clear_error(StatementClass *self)
|
||||||
{
|
{
|
||||||
@ -616,8 +611,10 @@ SC_clear_error(StatementClass *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function creates an error msg which is the concatenation */
|
/*
|
||||||
/* of the result, statement, connection, and socket messages. */
|
* This function creates an error msg which is the concatenation
|
||||||
|
* of the result, statement, connection, and socket messages.
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
SC_create_errormsg(StatementClass *self)
|
SC_create_errormsg(StatementClass *self)
|
||||||
{
|
{
|
||||||
@ -654,6 +651,7 @@ SC_create_errormsg(StatementClass *self)
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
SC_get_error(StatementClass *self, int *number, char **message)
|
SC_get_error(StatementClass *self, int *number, char **message)
|
||||||
{
|
{
|
||||||
@ -679,9 +677,11 @@ SC_get_error(StatementClass *self, int *number, char **message)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently, the driver offers very simple bookmark support -- it is
|
|
||||||
just the current row number. But it could be more sophisticated
|
/*
|
||||||
someday, such as mapping a key to a 32 bit value
|
* Currently, the driver offers very simple bookmark support -- it is
|
||||||
|
* just the current row number. But it could be more sophisticated
|
||||||
|
* someday, such as mapping a key to a 32 bit value
|
||||||
*/
|
*/
|
||||||
unsigned long
|
unsigned long
|
||||||
SC_get_bookmark(StatementClass *self)
|
SC_get_bookmark(StatementClass *self)
|
||||||
@ -689,6 +689,7 @@ SC_get_bookmark(StatementClass *self)
|
|||||||
return (self->currTuple + 1);
|
return (self->currTuple + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE
|
RETCODE
|
||||||
SC_fetch(StatementClass *self)
|
SC_fetch(StatementClass *self)
|
||||||
{
|
{
|
||||||
@ -711,11 +712,9 @@ SC_fetch(StatementClass *self)
|
|||||||
|
|
||||||
if (self->manual_result || !globals.use_declarefetch)
|
if (self->manual_result || !globals.use_declarefetch)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
|
if (self->currTuple >= QR_get_num_tuples(res) - 1 ||
|
||||||
(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
|
(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1))
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if at the end of the tuples, return "no data found" and set
|
* if at the end of the tuples, return "no data found" and set
|
||||||
* the cursor past the end of the result set
|
* the cursor past the end of the result set
|
||||||
@ -729,7 +728,6 @@ SC_fetch(StatementClass *self)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/* read from the cache or the physical next tuple */
|
/* read from the cache or the physical next tuple */
|
||||||
retval = QR_next_tuple(res);
|
retval = QR_next_tuple(res);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
@ -739,7 +737,6 @@ SC_fetch(StatementClass *self)
|
|||||||
}
|
}
|
||||||
else if (retval > 0)
|
else if (retval > 0)
|
||||||
(self->currTuple)++;/* all is well */
|
(self->currTuple)++;/* all is well */
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mylog("SQLFetch: error\n");
|
mylog("SQLFetch: error\n");
|
||||||
@ -772,7 +769,6 @@ SC_fetch(StatementClass *self)
|
|||||||
|
|
||||||
for (lf = 0; lf < num_cols; lf++)
|
for (lf = 0; lf < num_cols; lf++)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
|
||||||
|
|
||||||
/* reset for SQLGetData */
|
/* reset for SQLGetData */
|
||||||
@ -828,8 +824,8 @@ SC_fetch(StatementClass *self)
|
|||||||
result = SQL_SUCCESS_WITH_INFO;
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COPY_GENERAL_ERROR: /* error msg already
|
/* error msg already filled in */
|
||||||
* filled in */
|
case COPY_GENERAL_ERROR:
|
||||||
SC_log_error(func, "", self);
|
SC_log_error(func, "", self);
|
||||||
result = SQL_ERROR;
|
result = SQL_ERROR;
|
||||||
break;
|
break;
|
||||||
@ -908,13 +904,10 @@ SC_execute(StatementClass *self)
|
|||||||
CC_set_in_trans(conn);
|
CC_set_in_trans(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
oldstatus = conn->status;
|
oldstatus = conn->status;
|
||||||
conn->status = CONN_EXECUTING;
|
conn->status = CONN_EXECUTING;
|
||||||
self->status = STMT_EXECUTING;
|
self->status = STMT_EXECUTING;
|
||||||
|
|
||||||
|
|
||||||
/* If it's a SELECT statement, use a cursor. */
|
/* If it's a SELECT statement, use a cursor. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -924,19 +917,16 @@ SC_execute(StatementClass *self)
|
|||||||
/* in copy_statement... */
|
/* in copy_statement... */
|
||||||
if (self->statement_type == STMT_TYPE_SELECT)
|
if (self->statement_type == STMT_TYPE_SELECT)
|
||||||
{
|
{
|
||||||
|
|
||||||
char fetch[128];
|
char fetch[128];
|
||||||
|
|
||||||
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
||||||
|
|
||||||
|
|
||||||
/* send the declare/select */
|
/* send the declare/select */
|
||||||
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
|
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
|
||||||
|
|
||||||
if (globals.use_declarefetch && self->result != NULL &&
|
if (globals.use_declarefetch && self->result != NULL &&
|
||||||
QR_command_successful(self->result))
|
QR_command_successful(self->result))
|
||||||
{
|
{
|
||||||
|
|
||||||
QR_Destructor(self->result);
|
QR_Destructor(self->result);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -954,20 +944,15 @@ SC_execute(StatementClass *self)
|
|||||||
* will correct for any discrepancies in sizes and adjust the
|
* will correct for any discrepancies in sizes and adjust the
|
||||||
* cache accordingly.
|
* cache accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
|
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
|
||||||
|
|
||||||
self->result = CC_send_query(conn, fetch, &qi);
|
self->result = CC_send_query(conn, fetch, &qi);
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog(" done sending the query:\n");
|
mylog(" done sending the query:\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* not a SELECT statement so don't use a
|
{
|
||||||
* cursor */
|
/* not a SELECT statement so don't use a cursor */
|
||||||
mylog(" it's NOT a select statement: stmt=%u\n", self);
|
mylog(" it's NOT a select statement: stmt=%u\n", self);
|
||||||
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
|
self->result = CC_send_query(conn, self->stmt_with_params, NULL);
|
||||||
|
|
||||||
@ -986,7 +971,6 @@ SC_execute(StatementClass *self)
|
|||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
CC_set_no_trans(conn);
|
CC_set_no_trans(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->status = oldstatus;
|
conn->status = oldstatus;
|
||||||
@ -995,7 +979,6 @@ SC_execute(StatementClass *self)
|
|||||||
/* Check the status of the result */
|
/* Check the status of the result */
|
||||||
if (self->result)
|
if (self->result)
|
||||||
{
|
{
|
||||||
|
|
||||||
was_ok = QR_command_successful(self->result);
|
was_ok = QR_command_successful(self->result);
|
||||||
was_nonfatal = QR_command_nonfatal(self->result);
|
was_nonfatal = QR_command_nonfatal(self->result);
|
||||||
|
|
||||||
@ -1004,8 +987,8 @@ SC_execute(StatementClass *self)
|
|||||||
else
|
else
|
||||||
self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
|
self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
|
||||||
|
|
||||||
self->currTuple = -1; /* set cursor before the first tuple in
|
/* set cursor before the first tuple in the list */
|
||||||
* the list */
|
self->currTuple = -1;
|
||||||
self->current_col = -1;
|
self->current_col = -1;
|
||||||
self->rowset_start = -1;
|
self->rowset_start = -1;
|
||||||
|
|
||||||
@ -1029,9 +1012,8 @@ SC_execute(StatementClass *self)
|
|||||||
CC_abort(conn);
|
CC_abort(conn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Bad Error -- The error message will be
|
{
|
||||||
* in the Connection */
|
/* Bad Error -- The error message will be in the Connection */
|
||||||
|
|
||||||
if (self->statement_type == STMT_TYPE_CREATE)
|
if (self->statement_type == STMT_TYPE_CREATE)
|
||||||
{
|
{
|
||||||
self->errornumber = STMT_CREATE_TABLE_ERROR;
|
self->errornumber = STMT_CREATE_TABLE_ERROR;
|
||||||
@ -1069,6 +1051,7 @@ SC_execute(StatementClass *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SC_log_error(char *func, char *desc, StatementClass *self)
|
SC_log_error(char *func, char *desc, StatementClass *self)
|
||||||
{
|
{
|
||||||
|
@ -1,23 +1,27 @@
|
|||||||
/* Module: tuple.c
|
/*-------
|
||||||
|
* Module: tuple.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions for setting the data for individual
|
* Description: This module contains functions for setting the data
|
||||||
* fields (TupleField structure) of a manual result set.
|
* for individual fields (TupleField structure) of a
|
||||||
|
* manual result set.
|
||||||
*
|
*
|
||||||
* Important Note: These functions are ONLY used in building manual result sets for
|
* Important Note: These functions are ONLY used in building manual
|
||||||
* info functions (SQLTables, SQLColumns, etc.)
|
* result sets for info functions (SQLTables,
|
||||||
|
* SQLColumns, etc.)
|
||||||
*
|
*
|
||||||
* 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 "tuple.h"
|
#include "tuple.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_tuplefield_null(TupleField *tuple_field)
|
set_tuplefield_null(TupleField *tuple_field)
|
||||||
{
|
{
|
||||||
@ -25,6 +29,7 @@ set_tuplefield_null(TupleField *tuple_field)
|
|||||||
tuple_field->value = NULL; /* strdup(""); */
|
tuple_field->value = NULL; /* strdup(""); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_tuplefield_string(TupleField *tuple_field, char *string)
|
set_tuplefield_string(TupleField *tuple_field, char *string)
|
||||||
{
|
{
|
||||||
@ -39,7 +44,6 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
|
|||||||
{
|
{
|
||||||
char buffer[10];
|
char buffer[10];
|
||||||
|
|
||||||
|
|
||||||
sprintf(buffer, "%d", value);
|
sprintf(buffer, "%d", value);
|
||||||
|
|
||||||
tuple_field->len = strlen(buffer) + 1;
|
tuple_field->len = strlen(buffer) + 1;
|
||||||
@ -47,6 +51,7 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
|
|||||||
tuple_field->value = strdup(buffer);
|
tuple_field->value = strdup(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_tuplefield_int4(TupleField *tuple_field, Int4 value)
|
set_tuplefield_int4(TupleField *tuple_field, Int4 value)
|
||||||
{
|
{
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
/* Module: tuplelist.c
|
/*--------
|
||||||
|
* Module: tuplelist.c
|
||||||
*
|
*
|
||||||
* Description: This module contains functions for creating a manual result set
|
* Description: This module contains functions for creating a manual
|
||||||
* (the TupleList) and retrieving data from it for a specific row/column.
|
* result set (the TupleList) and retrieving data from
|
||||||
|
* it for a specific row/column.
|
||||||
*
|
*
|
||||||
* Classes: TupleListClass (Functions prefix: "TL_")
|
* Classes: TupleListClass (Functions prefix: "TL_")
|
||||||
*
|
*
|
||||||
* 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 <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "tuplelist.h"
|
#include "tuplelist.h"
|
||||||
#include "tuple.h"
|
#include "tuple.h"
|
||||||
|
|
||||||
|
|
||||||
TupleListClass *
|
TupleListClass *
|
||||||
TL_Constructor(UInt4 fieldcnt)
|
TL_Constructor(UInt4 fieldcnt)
|
||||||
{
|
{
|
||||||
@ -25,7 +28,6 @@ TL_Constructor(UInt4 fieldcnt)
|
|||||||
rv = (TupleListClass *) malloc(sizeof(TupleListClass));
|
rv = (TupleListClass *) malloc(sizeof(TupleListClass));
|
||||||
if (rv)
|
if (rv)
|
||||||
{
|
{
|
||||||
|
|
||||||
rv->num_fields = fieldcnt;
|
rv->num_fields = fieldcnt;
|
||||||
rv->num_tuples = 0;
|
rv->num_tuples = 0;
|
||||||
rv->list_start = NULL;
|
rv->list_start = NULL;
|
||||||
@ -39,6 +41,7 @@ TL_Constructor(UInt4 fieldcnt)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TL_Destructor(TupleListClass *self)
|
TL_Destructor(TupleListClass *self)
|
||||||
{
|
{
|
||||||
@ -134,7 +137,6 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
|
|||||||
}
|
}
|
||||||
else if (start_is_closer)
|
else if (start_is_closer)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the shortest way is to start the search from the head of the
|
* the shortest way is to start the search from the head of the
|
||||||
* list
|
* list
|
||||||
@ -177,11 +179,9 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
TL_add_tuple(TupleListClass *self, TupleNode *new_field)
|
TL_add_tuple(TupleListClass *self, TupleNode *new_field)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we append the tuple at the end of the doubly linked list of the
|
* we append the tuple at the end of the doubly linked list of the
|
||||||
* tuples we have already read in
|
* tuples we have already read in
|
||||||
@ -200,7 +200,6 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* there is already an element in the list, so add the new one at
|
* there is already an element in the list, so add the new one at
|
||||||
* the end of the list
|
* the end of the list
|
||||||
|
Reference in New Issue
Block a user