Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
296e7ba2
Commit
296e7ba2
authored
May 08, 2001
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ODBC source code cleanup patch. Should match rest of PostgreSQL code better.
parent
062a79a9
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
990 additions
and
1182 deletions
+990
-1182
src/interfaces/odbc/bind.c
src/interfaces/odbc/bind.c
+45
-44
src/interfaces/odbc/columninfo.c
src/interfaces/odbc/columninfo.c
+13
-12
src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.c
+79
-68
src/interfaces/odbc/convert.c
src/interfaces/odbc/convert.c
+97
-112
src/interfaces/odbc/dlg_specific.c
src/interfaces/odbc/dlg_specific.c
+24
-38
src/interfaces/odbc/drvconn.c
src/interfaces/odbc/drvconn.c
+14
-23
src/interfaces/odbc/environ.c
src/interfaces/odbc/environ.c
+17
-22
src/interfaces/odbc/execute.c
src/interfaces/odbc/execute.c
+35
-66
src/interfaces/odbc/gpps.c
src/interfaces/odbc/gpps.c
+27
-46
src/interfaces/odbc/info.c
src/interfaces/odbc/info.c
+103
-144
src/interfaces/odbc/lobj.c
src/interfaces/odbc/lobj.c
+11
-19
src/interfaces/odbc/misc.c
src/interfaces/odbc/misc.c
+33
-21
src/interfaces/odbc/multibyte.c
src/interfaces/odbc/multibyte.c
+22
-19
src/interfaces/odbc/options.c
src/interfaces/odbc/options.c
+45
-62
src/interfaces/odbc/parse.c
src/interfaces/odbc/parse.c
+28
-60
src/interfaces/odbc/pgtypes.c
src/interfaces/odbc/pgtypes.c
+81
-62
src/interfaces/odbc/psqlodbc.c
src/interfaces/odbc/psqlodbc.c
+16
-15
src/interfaces/odbc/qresult.c
src/interfaces/odbc/qresult.c
+72
-57
src/interfaces/odbc/results.c
src/interfaces/odbc/results.c
+76
-123
src/interfaces/odbc/setup.c
src/interfaces/odbc/setup.c
+60
-65
src/interfaces/odbc/socket.c
src/interfaces/odbc/socket.c
+15
-14
src/interfaces/odbc/statement.c
src/interfaces/odbc/statement.c
+57
-74
src/interfaces/odbc/tuple.c
src/interfaces/odbc/tuple.c
+12
-7
src/interfaces/odbc/tuplelist.c
src/interfaces/odbc/tuplelist.c
+8
-9
No files found.
src/interfaces/odbc/bind.c
View file @
296e7ba2
/* Module: bind.c
/*-------
* Module: bind.c
*
* Description: This module contains routines related to binding
* columns and parameters.
...
...
@@ -9,7 +10,7 @@
* SQLParamOptions(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -33,8 +34,8 @@
#include "sqlext.h"
#endif
/* Bind parameters on a statement handle */
/* Bind parameters on a statement handle */
RETCODE
SQL_API
SQLBindParameter
(
HSTMT
hstmt
,
...
...
@@ -112,8 +113,8 @@ SQLBindParameter(
}
}
ipar
--
;
/* use zero based column numbers for the
* below part */
/* use zero based column numbers for the below part */
ipar
--
;
/* store the given info */
stmt
->
parameters
[
ipar
].
buflen
=
cbValueMax
;
...
...
@@ -158,9 +159,8 @@ SQLBindParameter(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
/*
Associate a user-supplied buffer with a database column. */
/*
Associate a user-supplied buffer with a database column. */
RETCODE
SQL_API
SQLBindCol
(
HSTMT
hstmt
,
...
...
@@ -197,7 +197,6 @@ SQLBindCol(
/* If the bookmark column is being bound, then just save it */
if
(
icol
==
0
)
{
if
(
rgbValue
==
NULL
)
{
stmt
->
bookmark
.
buffer
=
NULL
;
...
...
@@ -220,10 +219,12 @@ SQLBindCol(
return
SQL_SUCCESS
;
}
/* allocate enough bindings if not already done */
/* Most likely, execution of a statement would have setup the */
/* necessary bindings. But some apps call BindCol before any */
/* statement is executed. */
/*
* Allocate enough bindings if not already done.
* Most likely, execution of a statement would have setup the
* necessary bindings. But some apps call BindCol before any
* statement is executed.
*/
if
(
icol
>
stmt
->
bindings_allocated
)
extend_bindings
(
stmt
,
icol
);
...
...
@@ -236,8 +237,8 @@ SQLBindCol(
return
SQL_ERROR
;
}
icol
--
;
/* use zero based col numbers from here
* out */
/* use zero based col numbers from here out */
icol
--
;
/* Reset for SQLGetData */
stmt
->
bindings
[
icol
].
data_left
=
-
1
;
...
...
@@ -264,15 +265,15 @@ SQLBindCol(
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
SQLDescribeParam
(
HSTMT
hstmt
,
...
...
@@ -323,10 +324,8 @@ SQLDescribeParam(
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
SQLParamOptions
(
HSTMT
hstmt
,
...
...
@@ -341,15 +340,16 @@ SQLParamOptions(
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 */
/* Postgres doesn't support that, the driver should just count the number of markers */
/* and return that. The reason the driver just can't say this function is unsupported */
/* like it does for SQLDescribeParam is that some applications don't care and try */
/* to call it anyway. */
/* If the statement does not have parameters, it should just return 0. */
/*
* This function should really talk to the dbms to determine the number of
* "parameter markers" (not bound parameters) in the statement. But, since
* Postgres doesn't support that, the driver should just count the number of markers
* and return that. The reason the driver just can't say this function is unsupported
* like it does for SQLDescribeParam is that some applications don't care and try
* to call it anyway.
* If the statement does not have parameters, it should just return 0.
*/
RETCODE
SQL_API
SQLNumParams
(
HSTMT
hstmt
,
...
...
@@ -387,10 +387,8 @@ SQLNumParams(
}
else
{
for
(
i
=
0
;
i
<
strlen
(
stmt
->
statement
);
i
++
)
{
if
(
stmt
->
statement
[
i
]
==
'?'
&&
!
in_quote
)
(
*
pcpar
)
++
;
else
...
...
@@ -399,12 +397,12 @@ SQLNumParams(
in_quote
=
(
in_quote
?
FALSE
:
TRUE
);
}
}
return
SQL_SUCCESS
;
}
}
/********************************************************************
/*
* Bindings Implementation
*/
BindInfoClass
*
...
...
@@ -428,6 +426,7 @@ create_empty_bindings(int num_columns)
return
new_bindings
;
}
void
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
);
/* 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
)
{
new_bindings
=
create_empty_bindings
(
num_columns
);
if
(
!
new_bindings
)
{
...
...
@@ -466,11 +466,12 @@ extend_bindings(StatementClass *stmt, int num_columns)
stmt
->
bindings
=
new_bindings
;
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, */
/* let it worry about it by unbinding those columns. */
/*
* There is no reason to zero out extra bindings if there are
* 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 */
/* SQLExecDirect(...) # returns 5 cols */
...
...
src/interfaces/odbc/columninfo.c
View file @
296e7ba2
/* Module: columninfo.c
/*-------
* Module: columninfo.c
*
* Description: This module contains routines related to
* reading and storing the field information from a query.
...
...
@@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#include "columninfo.h"
...
...
@@ -37,6 +38,7 @@ CI_Constructor()
return
rv
;
}
void
CI_Destructor
(
ColumnInfoClass
*
self
)
{
...
...
@@ -45,10 +47,12 @@ CI_Destructor(ColumnInfoClass *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
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
);
if
(
self
)
{
/* according to that allocate memory */
/* according to that allocate memory */
CI_set_num_fields
(
self
,
new_num_fields
);
}
/* now read in the descriptions */
for
(
lf
=
0
;
lf
<
new_num_fields
;
lf
++
)
{
SOCK_get_string
(
sock
,
new_field_name
,
2
*
MAX_COLUMN_LEN
);
new_adtid
=
(
Oid
)
SOCK_get_int
(
sock
,
4
);
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
(
PG_VERSION_GE
(
conn
,
6
.
4
))
{
mylog
(
"READING ATTTYPMOD
\n
"
);
new_atttypmod
=
(
Int4
)
SOCK_get_int
(
sock
,
4
);
...
...
@@ -107,7 +108,6 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
}
void
CI_free_memory
(
ColumnInfoClass
*
self
)
{
...
...
@@ -143,6 +143,7 @@ CI_free_memory(ColumnInfoClass *self)
self
->
atttypmod
=
NULL
;
}
void
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
);
}
void
CI_set_field_info
(
ColumnInfoClass
*
self
,
int
field_num
,
char
*
new_name
,
Oid
new_adtid
,
Int2
new_adtsize
,
Int4
new_atttypmod
)
{
/* check bounds */
if
((
field_num
<
0
)
||
(
field_num
>=
self
->
num_fields
))
return
;
...
...
src/interfaces/odbc/connection.c
View file @
296e7ba2
/* Module: connection.c
/*------
* Module: connection.c
*
* Description: This module contains routines related to
* connecting to and disconnecting from the Postgres DBMS.
...
...
@@ -9,7 +10,7 @@
* SQLBrowseConnect(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
...
...
@@ -83,8 +84,6 @@ SQLAllocConnect(
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLConnect
(
HDBC
hdbc
,
...
...
@@ -140,7 +139,6 @@ SQLConnect(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLBrowseConnect
(
...
...
@@ -158,7 +156,6 @@ SQLBrowseConnect(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
/* Drop any hstmts open on hdbc and disconnect from database */
RETCODE
SQL_API
...
...
@@ -199,8 +196,6 @@ SQLDisconnect(
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLFreeConnect
(
HDBC
hdbc
)
...
...
@@ -235,11 +230,8 @@ SQLFreeConnect(
/*
*
* IMPLEMENTATION CONNECTION CLASS
*
*/
* IMPLEMENTATION CONNECTION CLASS
*/
ConnectionClass
*
CC_Constructor
()
{
...
...
@@ -249,7 +241,6 @@ CC_Constructor()
if
(
rv
!=
NULL
)
{
rv
->
henv
=
NULL
;
/* not yet associated with an environment */
rv
->
errormsg
=
NULL
;
...
...
@@ -301,7 +292,6 @@ CC_Constructor()
char
CC_Destructor
(
ConnectionClass
*
self
)
{
mylog
(
"enter CC_Destructor, self=%u
\n
"
,
self
);
if
(
self
->
status
==
CONN_EXECUTING
)
...
...
@@ -343,6 +333,7 @@ CC_Destructor(ConnectionClass *self)
return
1
;
}
/* Return how many cursors are opened on this connection */
int
CC_cursor_count
(
ConnectionClass
*
self
)
...
...
@@ -365,6 +356,7 @@ CC_cursor_count(ConnectionClass *self)
return
count
;
}
void
CC_clear_error
(
ConnectionClass
*
self
)
{
...
...
@@ -373,8 +365,11 @@ CC_clear_error(ConnectionClass *self)
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
CC_abort
(
ConnectionClass
*
self
)
{
...
...
@@ -399,6 +394,7 @@ CC_abort(ConnectionClass *self)
return
TRUE
;
}
/* This is called by SQLDisconnect also */
char
CC_cleanup
(
ConnectionClass
*
self
)
...
...
@@ -434,7 +430,6 @@ CC_cleanup(ConnectionClass *self)
stmt
=
self
->
stmts
[
i
];
if
(
stmt
)
{
stmt
->
hdbc
=
NULL
;
/* prevent any more dbase interactions */
SC_Destructor
(
stmt
);
...
...
@@ -456,6 +451,7 @@ CC_cleanup(ConnectionClass *self)
return
TRUE
;
}
int
CC_set_translation
(
ConnectionClass
*
self
)
{
...
...
@@ -499,6 +495,7 @@ CC_set_translation(ConnectionClass *self)
return
TRUE
;
}
char
CC_connect
(
ConnectionClass
*
self
,
char
do_password
)
{
...
...
@@ -521,7 +518,6 @@ CC_connect(ConnectionClass *self, char do_password)
else
{
qlog
(
"Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d
\n
"
,
POSTGRESDRIVERVERSION
,
globals
.
fetch_max
,
...
...
@@ -646,14 +642,13 @@ CC_connect(ConnectionClass *self, char do_password)
mylog
(
"gonna do authentication
\n
"
);
/*
*************************************************** */
/* Now get the authentication request from backend */
/* ***************************************************
*/
/*
* Now get the authentication request from backend
*/
if
(
!
PROTOCOL_62
(
ci
))
do
{
if
(
do_password
)
beresp
=
'R'
;
else
...
...
@@ -743,8 +738,10 @@ CC_connect(ConnectionClass *self, char do_password)
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
"
);
res
=
CC_send_query
(
self
,
" "
,
NULL
);
...
...
@@ -764,9 +761,9 @@ CC_connect(ConnectionClass *self, char do_password)
CC_set_translation
(
self
);
/*
*********************************************/
/******* Send any initial settings *********/
/*********************************************
*/
/*
* Send any initial settings
*/
/*
* Since these functions allocate statements, and since the connection
...
...
@@ -789,6 +786,7 @@ CC_connect(ConnectionClass *self, char do_password)
}
char
CC_add_statement
(
ConnectionClass
*
self
,
StatementClass
*
stmt
)
{
...
...
@@ -821,6 +819,7 @@ CC_add_statement(ConnectionClass *self, StatementClass *stmt)
return
TRUE
;
}
char
CC_remove_statement
(
ConnectionClass
*
self
,
StatementClass
*
stmt
)
{
...
...
@@ -838,9 +837,11 @@ CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
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
*
CC_create_errormsg
(
ConnectionClass
*
self
)
{
...
...
@@ -897,14 +898,15 @@ 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
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
'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/
/*
* 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
* 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
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/
QResultClass
*
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
;
/* ERROR_MSG_LENGTH is suffcient */
static
char
msgbuffer
[
ERROR_MSG_LENGTH
+
1
];
char
cmdbuffer
[
ERROR_MSG_LENGTH
+
1
];
/* QR_set_command() dups
* this string so dont
* need static */
/* QR_set_command() dups this string so doesn't need static */
char
cmdbuffer
[
ERROR_MSG_LENGTH
+
1
];
mylog
(
"send_query(): 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
{
char
clear
=
0
;
mylog
(
"send_query: ok - 'C' - %s
\n
"
,
cmdbuffer
);
...
...
@@ -1203,6 +1202,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
}
}
int
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
)
{
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
);
...
...
@@ -1373,9 +1372,10 @@ CC_send_settings(ConnectionClass *self)
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
);
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
...
...
@@ -1457,10 +1457,12 @@ CC_send_settings(ConnectionClass *self)
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
CC_lookup_lo
(
ConnectionClass
*
self
)
{
...
...
@@ -1471,9 +1473,10 @@ CC_lookup_lo(ConnectionClass *self)
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
);
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
return
;
...
...
@@ -1506,10 +1509,12 @@ CC_lookup_lo(ConnectionClass *self)
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
CC_initialize_pg_version
(
ConnectionClass
*
self
)
{
...
...
@@ -1534,10 +1539,12 @@ 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
CC_lookup_pg_version
(
ConnectionClass
*
self
)
{
...
...
@@ -1551,9 +1558,10 @@ CC_lookup_pg_version(ConnectionClass *self)
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
);
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
return
;
...
...
@@ -1581,8 +1589,10 @@ CC_lookup_pg_version(ConnectionClass *self)
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"
);
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
);
}
void
CC_log_error
(
char
*
func
,
char
*
desc
,
ConnectionClass
*
self
)
{
...
...
src/interfaces/odbc/convert.c
View file @
296e7ba2
/* Module: convert.c
/*-------
* Module: convert.c
*
* Description: This module contains routines related to
* converting parameters and columns into requested data types.
...
...
@@ -12,7 +13,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
...
...
@@ -64,11 +65,11 @@ typedef signed char SCHAR;
extern
GLOBAL_VALUES
globals
;
/*
How to map ODBC scalar functions {fn func(args)} to Postgres
*
This is just a simple substitution
*
List augmented from
*
http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
* - thomas 2000-04-03
/*
*
How to map ODBC scalar functions {fn func(args)} to Postgres.
*
This is just a simple substitution. List augmented from:
* http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
*
- thomas 2000-04-03
*/
char
*
mapFuncs
[][
2
]
=
{
/* { "ASCII", "ascii" }, */
...
...
@@ -141,21 +142,24 @@ unsigned int conv_from_octal(unsigned char *s);
unsigned
int
conv_from_hex
(
unsigned
char
*
s
);
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() */
...
...
@@ -168,6 +172,7 @@ copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *val
(
SDWORD
)
bic
->
buflen
,
(
SDWORD
*
)
bic
->
used
);
}
/* This is called by SQLGetData() */
int
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
;
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
)
{
pcbValueOffset
=
rgbValueOffset
=
(
bind_size
*
bind_row
);
}
else
{
pcbValueOffset
=
bind_row
*
sizeof
(
SDWORD
);
rgbValueOffset
=
bind_row
*
cbValueMax
;
...
...
@@ -215,14 +221,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
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
)
*
(
SDWORD
*
)
((
char
*
)
pcbValue
+
pcbValueOffset
)
=
SQL_NULL_DATA
;
return
COPY_OK
;
}
if
(
stmt
->
hdbc
->
DataSourceToDriver
!=
NULL
)
{
int
length
=
strlen
(
value
);
...
...
@@ -234,21 +241,19 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
NULL
,
0
,
NULL
);
}
/********************************************************************
First convert any specific postgres types into more
useable data.
NOTE: Conversions from PG char/varchar of a date/time/timestamp
value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*********************************************************************/
/*
* First convert any specific postgres types into more
* useable data.
*
* NOTE: Conversions from PG char/varchar of a date/time/timestamp
* value to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
*/
switch
(
field_type
)
{
/*
* $$$ need to add parsing for date/time/timestamp strings in
* PG_TYPE_CHAR,VARCHAR $$$
*/
/*
* $$$ need to add parsing for date/time/timestamp strings in
* PG_TYPE_CHAR,VARCHAR $$$
*/
case
PG_TYPE_DATE
:
sscanf
(
value
,
"%4d-%2d-%2d"
,
&
st
.
y
,
&
st
.
m
,
&
st
.
d
);
break
;
...
...
@@ -261,13 +266,13 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
case
PG_TYPE_DATETIME
:
case
PG_TYPE_TIMESTAMP
:
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
);
}
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
;
tim
=
localtime
(
&
t
);
st
.
m
=
tim
->
tm_mon
+
1
;
...
...
@@ -290,7 +295,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
}
break
;
/* This is for internal use by SQLStatistics() */
/* This is for internal use by SQLStatistics() */
case
PG_TYPE_INT2VECTOR
:
{
int
nval
,
...
...
@@ -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
);
}
rgbValueBindRow
=
(
char
*
)
rgbValue
+
rgbValueOffset
;
if
(
fCType
==
SQL_C_CHAR
)
{
/* Special character formatting as required */
/*
* These really should return error if cbValueMax is not big
* enough.
...
...
@@ -456,7 +457,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if
(
cbValueMax
>
0
)
{
copy_len
=
(
len
>=
cbValueMax
)
?
cbValueMax
-
1
:
len
;
/* Copy the data */
...
...
@@ -483,7 +483,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
}
else
{
/*
* 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
...
...
@@ -633,7 +632,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
if
(
stmt
->
current_col
>=
0
)
{
/* No more data left for this column */
if
(
stmt
->
bindings
[
stmt
->
current_col
].
data_left
==
0
)
return
COPY_NO_DATA_FOUND
;
...
...
@@ -690,10 +688,11 @@ 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 no longer does any dynamic memory allocation!
*/
/*
* This function inserts parameters into an SQL statements.
* It will also modify a SELECT statement for use with declare/fetch cursors.
* This function no longer does any dynamic memory allocation!
*/
int
copy_statement_with_parameters
(
StatementClass
*
stmt
)
{
...
...
@@ -760,7 +759,6 @@ copy_statement_with_parameters(StatementClass *stmt)
for
(
opos
=
0
;
opos
<
oldstmtlen
;
opos
++
)
{
/* Squeeze carriage-return/linefeed pairs to linefeed only */
if
(
old_statement
[
opos
]
==
'\r'
&&
opos
+
1
<
oldstmtlen
&&
old_statement
[
opos
+
1
]
==
'\n'
)
...
...
@@ -782,10 +780,8 @@ copy_statement_with_parameters(StatementClass *stmt)
#ifdef MULTIBYTE
char
*
end
=
multibyte_strchr
(
begin
,
'}'
);
#else
char
*
end
=
strchr
(
begin
,
'}'
);
#endif
if
(
!
end
)
...
...
@@ -807,12 +803,9 @@ copy_statement_with_parameters(StatementClass *stmt)
}
opos
+=
end
-
begin
+
1
;
*
end
=
'}'
;
continue
;
}
/*
* Can you have parameter markers inside of quotes? I dont think
* so. All the queries I've seen expect the driver to put quotes
...
...
@@ -829,12 +822,9 @@ copy_statement_with_parameters(StatementClass *stmt)
continue
;
}
/****************************************************/
/* Its a '?' parameter alright */
/****************************************************/
/*
* Its a '?' parameter alright
*/
param_number
++
;
if
(
param_number
>=
stmt
->
parameters_allocated
)
...
...
@@ -906,7 +896,6 @@ copy_statement_with_parameters(StatementClass *stmt)
param_string
[
0
]
=
'\0'
;
cbuf
[
0
]
=
'\0'
;
/* Convert input C type to a neutral format */
switch
(
param_ctype
)
{
...
...
@@ -1113,13 +1102,10 @@ copy_statement_with_parameters(StatementClass *stmt)
if
(
stmt
->
parameters
[
param_number
].
data_at_exec
)
{
lobj_oid
=
stmt
->
parameters
[
param_number
].
lobj_oid
;
}
else
{
/* begin transaction if needed */
if
(
!
CC_is_in_trans
(
stmt
->
hdbc
))
{
...
...
@@ -1264,15 +1250,12 @@ copy_statement_with_parameters(StatementClass *stmt)
new_statement
[
npos
++
]
=
'\''
;
/* Close Quote */
break
;
}
}
/* end, for */
/* make sure new_statement is always null-terminated */
new_statement
[
npos
]
=
'\0'
;
if
(
stmt
->
hdbc
->
DriverToDataSource
!=
NULL
)
{
int
length
=
strlen
(
new_statement
);
...
...
@@ -1284,10 +1267,10 @@ copy_statement_with_parameters(StatementClass *stmt)
NULL
,
0
,
NULL
);
}
return
SQL_SUCCESS
;
}
char
*
mapFunction
(
char
*
func
)
{
...
...
@@ -1300,7 +1283,10 @@ mapFunction(char *func)
return
NULL
;
}
/* convert_escape()
/*
* convert_escape()
*
* This function returns a pointer to static memory!
*/
char
*
...
...
@@ -1330,7 +1316,6 @@ convert_escape(char *value)
}
else
if
(
strcmp
(
key
,
"fn"
)
==
0
)
{
/*
* Function invocation Separate off the func name, skipping
* trailing whitespace.
...
...
@@ -1381,7 +1366,6 @@ convert_escape(char *value)
}
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 */
/* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value */
/*
* 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
*/
char
parse_datetime
(
char
*
buf
,
SIMPLE_TIME
*
st
)
{
...
...
@@ -1465,6 +1450,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st)
return
FALSE
;
}
/* Change linefeed to carriage-return/linefeed */
int
convert_linefeeds
(
char
*
si
,
char
*
dst
,
size_t
max
)
...
...
@@ -1493,9 +1479,11 @@ convert_linefeeds(char *si, char *dst, size_t max)
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
*
convert_special_chars
(
char
*
si
,
char
*
dst
,
int
used
)
{
...
...
@@ -1537,6 +1525,7 @@ convert_special_chars(char *si, char *dst, int used)
return
p
;
}
/* !!! Need to implement this function !!! */
int
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
;
}
unsigned
int
conv_from_octal
(
unsigned
char
*
s
)
{
...
...
@@ -1560,6 +1550,7 @@ conv_from_octal(unsigned char *s)
}
unsigned
int
conv_from_hex
(
unsigned
char
*
s
)
{
...
...
@@ -1569,7 +1560,6 @@ conv_from_hex(unsigned char *s)
for
(
i
=
1
;
i
<=
2
;
i
++
)
{
if
(
s
[
i
]
>=
'a'
&&
s
[
i
]
<=
'f'
)
val
=
s
[
i
]
-
'a'
+
10
;
else
if
(
s
[
i
]
>=
'A'
&&
s
[
i
]
<=
'F'
)
...
...
@@ -1583,6 +1573,7 @@ conv_from_hex(unsigned char *s)
return
y
;
}
/* convert octal escapes to bytes */
int
convert_from_pgbinary
(
unsigned
char
*
value
,
unsigned
char
*
rgbValue
,
int
cbValueMax
)
...
...
@@ -1629,6 +1620,7 @@ conv_to_octal(unsigned char val)
return
x
;
}
/* convert non-ascii bytes to octal escape sequences */
int
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
,
o
=
0
;
for
(
i
=
0
;
i
<
len
;
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
]));
o
+=
5
;
}
}
mylog
(
"convert_to_pgbinary: returning %d, out='%.*s'
\n
"
,
o
,
o
,
out
);
...
...
@@ -1705,21 +1695,22 @@ decode(char *in, char *out)
}
/* 1. get oid (from 'value')
2. open the large object
3. read from the large object (handle multiple GetData)
4. close when read less than requested? -OR-
lseek/read each time
handle case where application receives truncated and
decides not to continue reading.
CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
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
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.
*/
/*-------
* 1. get oid (from 'value')
* 2. open the large object
* 3. read from the large object (handle multiple GetData)
* 4. close when read less than requested? -OR-
* lseek/read each time
* handle case where application receives truncated and
* decides not to continue reading.
*
* CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
* 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
* 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.
*-------
*/
int
convert_lo
(
StatementClass
*
stmt
,
void
*
value
,
Int2
fCType
,
PTR
rgbValue
,
SDWORD
cbValueMax
,
SDWORD
*
pcbValue
)
...
...
@@ -1731,7 +1722,7 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
BindInfoClass
*
bindInfo
=
NULL
;
/* If using SQLGetData, then current_col will be set */
/* If using SQLGetData, then current_col will be set */
if
(
stmt
->
current_col
>=
0
)
{
bindInfo
=
&
stmt
->
bindings
[
stmt
->
current_col
];
...
...
@@ -1745,7 +1736,6 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
if
(
!
bindInfo
||
bindInfo
->
data_left
==
-
1
)
{
/* begin transaction if needed */
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
);
if
(
retval
>=
0
)
{
left
=
lo_tell
(
stmt
->
hdbc
,
stmt
->
lobj_fd
);
if
(
bindInfo
)
bindInfo
->
data_left
=
left
;
...
...
@@ -1849,11 +1838,9 @@ convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
if
(
pcbValue
)
*
pcbValue
=
left
<
0
?
SQL_NO_TOTAL
:
left
;
if
(
bindInfo
&&
bindInfo
->
data_left
>
0
)
bindInfo
->
data_left
-=
retval
;
if
(
!
bindInfo
||
bindInfo
->
data_left
==
0
)
{
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 */
}
return
result
;
}
src/interfaces/odbc/dlg_specific.c
View file @
296e7ba2
/* Module: dlg_specific.c
/*-------
* Module: dlg_specific.c
*
* Description: This module contains any specific code for handling
* dialog boxes such as driver/datasource options. Both the
...
...
@@ -12,7 +13,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
/* Multibyte support Eiji Tokuya 2001-03-15 */
...
...
@@ -50,11 +51,11 @@
extern
GLOBAL_VALUES
globals
;
#ifdef WIN32
void
SetDlgStuff
(
HWND
hdlg
,
ConnInfo
*
ci
)
{
/*
* If driver attribute NOT present, then set the datasource name and
* description
...
...
@@ -72,6 +73,7 @@ SetDlgStuff(HWND hdlg, ConnInfo *ci)
SetDlgItemText
(
hdlg
,
IDC_PORT
,
ci
->
port
);
}
void
GetDlgStuff
(
HWND
hdlg
,
ConnInfo
*
ci
)
{
...
...
@@ -85,7 +87,6 @@ GetDlgStuff(HWND hdlg, ConnInfo *ci)
}
int
CALLBACK
driver_optionsProc
(
HWND
hdlg
,
WORD
wMsg
,
...
...
@@ -141,7 +142,6 @@ driver_optionsProc(HWND hdlg,
switch
(
GET_WM_COMMAND_ID
(
wParam
,
lParam
))
{
case
IDOK
:
globals
.
commlog
=
IsDlgButtonChecked
(
hdlg
,
DRV_COMMLOG
);
globals
.
disable_optimizer
=
IsDlgButtonChecked
(
hdlg
,
DRV_OPTIMIZER
);
globals
.
ksqo
=
IsDlgButtonChecked
(
hdlg
,
DRV_KSQO
);
...
...
@@ -228,12 +228,12 @@ driver_optionsProc(HWND hdlg,
break
;
}
}
return
FALSE
;
}
int
CALLBACK
ds_optionsProc
(
HWND
hdlg
,
WORD
wMsg
,
...
...
@@ -267,11 +267,9 @@ ds_optionsProc(HWND hdlg,
else
if
(
strncmp
(
ci
->
protocol
,
PG63
,
strlen
(
PG63
))
==
0
)
CheckDlgButton
(
hdlg
,
DS_PG63
,
1
);
else
/* latest */
/* latest */
CheckDlgButton
(
hdlg
,
DS_PG64
,
1
);
CheckDlgButton
(
hdlg
,
DS_SHOWOIDCOLUMN
,
atoi
(
ci
->
show_oid_column
));
CheckDlgButton
(
hdlg
,
DS_FAKEOIDINDEX
,
atoi
(
ci
->
fake_oid_index
));
CheckDlgButton
(
hdlg
,
DS_ROWVERSIONING
,
atoi
(
ci
->
row_versioning
));
...
...
@@ -283,7 +281,6 @@ ds_optionsProc(HWND hdlg,
SetDlgItemText
(
hdlg
,
DS_CONNSETTINGS
,
ci
->
conn_settings
);
break
;
case
WM_COMMAND
:
switch
(
GET_WM_COMMAND_ID
(
wParam
,
lParam
))
{
...
...
@@ -292,9 +289,7 @@ ds_optionsProc(HWND hdlg,
EnableWindow
(
GetDlgItem
(
hdlg
,
DS_FAKEOIDINDEX
),
IsDlgButtonChecked
(
hdlg
,
DS_SHOWOIDCOLUMN
));
return
TRUE
;
case
IDOK
:
ci
=
(
ConnInfo
*
)
GetWindowLong
(
hdlg
,
DWL_USER
);
mylog
(
"IDOK: got ci = %u
\n
"
,
ci
);
...
...
@@ -307,7 +302,7 @@ ds_optionsProc(HWND hdlg,
else
if
(
IsDlgButtonChecked
(
hdlg
,
DS_PG63
))
strcpy
(
ci
->
protocol
,
PG63
);
else
/* latest */
/* latest */
strcpy
(
ci
->
protocol
,
PG64
);
sprintf
(
ci
->
show_system_tables
,
"%d"
,
IsDlgButtonChecked
(
hdlg
,
DS_SHOWSYSTEMTABLES
));
...
...
@@ -321,7 +316,6 @@ ds_optionsProc(HWND hdlg,
/* Datasource Connection Settings */
GetDlgItemText
(
hdlg
,
DS_CONNSETTINGS
,
ci
->
conn_settings
,
sizeof
(
ci
->
conn_settings
));
/* fall through */
case
IDCANCEL
:
...
...
@@ -335,6 +329,7 @@ ds_optionsProc(HWND hdlg,
#endif
/* WIN32 */
void
makeConnectString
(
char
*
connect_string
,
ConnInfo
*
ci
)
{
...
...
@@ -365,10 +360,10 @@ makeConnectString(char *connect_string, ConnInfo *ci)
encoded_conn_settings
);
}
void
copyAttributes
(
ConnInfo
*
ci
,
char
*
attribute
,
char
*
value
)
{
if
(
stricmp
(
attribute
,
"DSN"
)
==
0
)
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
);
}
void
getDSNdefaults
(
ConnInfo
*
ci
)
{
...
...
@@ -450,8 +445,10 @@ getDSNinfo(ConnInfo *ci, char overwrite)
char
*
DSN
=
ci
->
dsn
;
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
(
ci
->
driver
[
0
]
!=
'\0'
)
...
...
@@ -514,11 +511,9 @@ getDSNinfo(ConnInfo *ci, char overwrite)
if
(
ci
->
translation_option
[
0
]
==
'\0'
||
overwrite
)
SQLGetPrivateProfileString
(
DSN
,
INI_TRANSLATIONOPTION
,
""
,
ci
->
translation_option
,
sizeof
(
ci
->
translation_option
),
ODBC_INI
);
/* Allow override of odbcinst.ini parameters here */
getGlobalDefaults
(
DSN
,
ODBC_INI
,
TRUE
);
qlog
(
"DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'
\n
"
,
DSN
,
ci
->
server
,
...
...
@@ -546,7 +541,6 @@ getDSNinfo(ConnInfo *ci, char overwrite)
qlog
(
" translation_dll='%s',translation_option='%s'
\n
"
,
ci
->
translation_dll
,
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
getGlobalDefaults
(
char
*
section
,
char
*
filename
,
char
override
)
{
char
temp
[
256
];
/* Fetch Count is stored in driver section */
SQLGetPrivateProfileString
(
section
,
INI_FETCH
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -648,7 +642,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
fetch_max
=
FETCH_MAX
;
/* Socket Buffersize is stored in driver section */
SQLGetPrivateProfileString
(
section
,
INI_SOCKET
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -657,7 +650,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
socket_buffersize
=
SOCK_BUFFER_SIZE
;
/* Debug is stored in the driver section */
SQLGetPrivateProfileString
(
section
,
INI_DEBUG
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -666,7 +658,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
debug
=
DEFAULT_DEBUG
;
/* CommLog is stored in the driver section */
SQLGetPrivateProfileString
(
section
,
INI_COMMLOG
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -675,7 +666,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
commlog
=
DEFAULT_COMMLOG
;
/* Optimizer is stored in the driver section only */
SQLGetPrivateProfileString
(
section
,
INI_OPTIMIZER
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -734,8 +724,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
cancel_as_freestmt
=
DEFAULT_CANCELASFREESTMT
;
/* UseDeclareFetch is stored in the driver section only */
SQLGetPrivateProfileString
(
section
,
INI_USEDECLAREFETCH
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -744,7 +732,6 @@ getGlobalDefaults(char *section, char *filename, char override)
else
if
(
!
override
)
globals
.
use_declarefetch
=
DEFAULT_USEDECLAREFETCH
;
/* Max Varchar Size */
SQLGetPrivateProfileString
(
section
,
INI_MAXVARCHARSIZE
,
""
,
temp
,
sizeof
(
temp
),
filename
);
...
...
@@ -804,7 +791,6 @@ getGlobalDefaults(char *section, char *filename, char override)
/* Dont allow override of an override! */
if
(
!
override
)
{
/*
* ConnSettings is stored in the driver section and per datasource
* for override
...
...
@@ -831,14 +817,14 @@ getGlobalDefaults(char *section, char *filename, char override)
strcpy
(
globals
.
protocol
,
temp
);
else
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
updateGlobals
(
void
)
{
...
...
src/interfaces/odbc/drvconn.c
View file @
296e7ba2
/* Module: drvconn.c
/*-------
* Module: drvconn.c
*
* Description: This module contains only routines related to
* implementing SQLDriverConnect.
...
...
@@ -8,7 +9,7 @@
* API functions: SQLDriverConnect
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -110,9 +111,11 @@ SQLDriverConnect(
/* Parse the connect string and fill in conninfo for this hdbc. */
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 */
/* of course there is a DSN given -- if not, it does nothing!) */
/*
* If the ConnInfo in the hdbc is missing anything,
* 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
);
/* Fill in any default parameters if they are not there. */
...
...
@@ -147,7 +150,6 @@ dialog:
ci
->
port
[
0
]
==
'\0'
||
password_required
)
{
dialog_result
=
dconn_DoDialog
(
hwnd
,
ci
);
if
(
dialog_result
!=
SQL_SUCCESS
)
return
dialog_result
;
...
...
@@ -173,12 +175,11 @@ dialog:
ci
->
database
[
0
]
==
'\0'
||
ci
->
port
[
0
]
==
'\0'
)
{
/*
(password_required && ci->password[0] == '\0')) */
/*
(password_required && ci->password[0] == '\0')) */
return
SQL_NO_DATA_FOUND
;
}
/* do the actual connect */
retval
=
CC_connect
(
conn
,
password_required
);
if
(
retval
<
0
)
...
...
@@ -206,9 +207,9 @@ dialog:
return
SQL_ERROR
;
}
/*
********************************************/
/* Create the Output Connection String */
/********************************************
*/
/*
* Create the Output Connection String
*/
result
=
SQL_SUCCESS
;
makeConnectString
(
connStrOut
,
ci
);
...
...
@@ -216,7 +217,6 @@ dialog:
if
(
szConnStrOut
)
{
/*
* Return the completed string to the caller. The correct method
* is to only construct the connect string if a dialog was put up,
...
...
@@ -247,6 +247,7 @@ dialog:
return
result
;
}
#ifdef WIN32
RETCODE
dconn_DoDialog
(
HWND
hwnd
,
ConnInfo
*
ci
)
...
...
@@ -296,7 +297,6 @@ dconn_FDriverConnectProc(
SetWindowLong
(
hdlg
,
DWL_USER
,
lParam
);
/* Save the ConnInfo for
* the "OK" */
SetDlgStuff
(
hdlg
,
ci
);
if
(
ci
->
database
[
0
]
==
'\0'
)
...
...
@@ -309,38 +309,29 @@ dconn_FDriverConnectProc(
SetFocus
(
GetDlgItem
(
hdlg
,
IDC_USER
));
else
if
(
ci
->
focus_password
)
SetFocus
(
GetDlgItem
(
hdlg
,
IDC_PASSWORD
));
break
;
case
WM_COMMAND
:
switch
(
GET_WM_COMMAND_ID
(
wParam
,
lParam
))
{
case
IDOK
:
ci
=
(
ConnInfo
*
)
GetWindowLong
(
hdlg
,
DWL_USER
);
GetDlgStuff
(
hdlg
,
ci
);
case
IDCANCEL
:
EndDialog
(
hdlg
,
GET_WM_COMMAND_ID
(
wParam
,
lParam
)
==
IDOK
);
return
TRUE
;
case
IDC_DRIVER
:
DialogBoxParam
(
s_hModule
,
MAKEINTRESOURCE
(
DLG_OPTIONS_DRV
),
hdlg
,
driver_optionsProc
,
(
LPARAM
)
NULL
);
break
;
case
IDC_DATASOURCE
:
ci
=
(
ConnInfo
*
)
GetWindowLong
(
hdlg
,
DWL_USER
);
DialogBoxParam
(
s_hModule
,
MAKEINTRESOURCE
(
DLG_OPTIONS_DS
),
hdlg
,
ds_optionsProc
,
(
LPARAM
)
ci
);
break
;
}
}
...
...
@@ -350,6 +341,7 @@ dconn_FDriverConnectProc(
#endif
/* WIN32 */
void
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
);
}
src/interfaces/odbc/environ.c
View file @
296e7ba2
/* Module: environ.c
/*-------
* Module: environ.c
*
* Description: This module contains routines related to
* the environment, such as storing connection handles,
...
...
@@ -9,7 +10,7 @@
* API functions: SQLAllocEnv, SQLFreeEnv, SQLError
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#include "environ.h"
...
...
@@ -54,6 +55,7 @@ SQLAllocEnv(HENV FAR *phenv)
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLFreeEnv
(
HENV
henv
)
{
...
...
@@ -73,8 +75,8 @@ SQLFreeEnv(HENV henv)
return
SQL_ERROR
;
}
/* Returns the next SQL error information. */
/* Returns the next SQL error information. */
RETCODE
SQL_API
SQLError
(
HENV
henv
,
...
...
@@ -208,24 +210,19 @@ SQLError(
case
STMT_INVALID_CURSOR_POSITION
:
strcpy
(
szSqlState
,
"S1109"
);
break
;
case
STMT_VALUE_OUT_OF_RANGE
:
strcpy
(
szSqlState
,
"22003"
);
break
;
case
STMT_OPERATION_INVALID
:
strcpy
(
szSqlState
,
"S1011"
);
break
;
case
STMT_EXEC_ERROR
:
default:
strcpy
(
szSqlState
,
"S1000"
);
/* also a general error */
break
;
}
mylog
(
" szSqlState = '%s', szError='%s'
\n
"
,
szSqlState
,
szErrorMsg
);
}
else
{
...
...
@@ -237,10 +234,11 @@ SQLError(
szErrorMsg
[
0
]
=
'\0'
;
mylog
(
" returning NO_DATA_FOUND
\n
"
);
return
SQL_NO_DATA_FOUND
;
}
return
SQL_SUCCESS
;
return
SQL_SUCCESS
;
}
else
if
(
SQL_NULL_HDBC
!=
hdbc
)
{
...
...
@@ -310,7 +308,6 @@ SQLError(
break
;
case
CONN_TRANSACT_IN_PROGRES
:
strcpy
(
szSqlState
,
"S1010"
);
/*
* when the user tries to switch commit mode in a
* transaction
...
...
@@ -324,18 +321,15 @@ SQLError(
case
STMT_NOT_IMPLEMENTED_ERROR
:
strcpy
(
szSqlState
,
"S1C00"
);
break
;
case
CONN_VALUE_OUT_OF_RANGE
:
case
STMT_VALUE_OUT_OF_RANGE
:
strcpy
(
szSqlState
,
"22003"
);
break
;
default:
strcpy
(
szSqlState
,
"S1000"
);
/* general error */
break
;
}
}
else
{
...
...
@@ -349,8 +343,8 @@ SQLError(
return
SQL_NO_DATA_FOUND
;
}
return
SQL_SUCCESS
;
return
SQL_SUCCESS
;
}
else
if
(
SQL_NULL_HENV
!=
henv
)
{
...
...
@@ -419,15 +413,10 @@ SQLError(
}
/*********************************************************************/
/*
* EnvironmentClass implementation
*/
EnvironmentClass
*
EnvironmentClass
*
EN_Constructor
(
void
)
{
EnvironmentClass
*
rv
;
...
...
@@ -451,8 +440,10 @@ EN_Destructor(EnvironmentClass *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 */
for
(
lf
=
0
;
lf
<
MAX_CONNECTIONS
;
lf
++
)
...
...
@@ -466,6 +457,7 @@ EN_Destructor(EnvironmentClass *self)
return
rv
;
}
char
EN_get_error
(
EnvironmentClass
*
self
,
int
*
number
,
char
**
message
)
{
...
...
@@ -481,6 +473,7 @@ EN_get_error(EnvironmentClass *self, int *number, char **message)
return
0
;
}
char
EN_add_connection
(
EnvironmentClass
*
self
,
ConnectionClass
*
conn
)
{
...
...
@@ -504,6 +497,7 @@ EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
return
FALSE
;
}
char
EN_remove_connection
(
EnvironmentClass
*
self
,
ConnectionClass
*
conn
)
{
...
...
@@ -519,6 +513,7 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
return
FALSE
;
}
void
EN_log_error
(
char
*
func
,
char
*
desc
,
EnvironmentClass
*
self
)
{
...
...
src/interfaces/odbc/execute.c
View file @
296e7ba2
/* Module: execute.c
/*-------
* Module: execute.c
*
* Description: This module contains routines related to
* preparing and executing an SQL statement.
...
...
@@ -9,7 +10,7 @@
* SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -126,14 +127,10 @@ SQLPrepare(HSTMT hstmt,
}
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
RETCODE
SQL_API
SQLExecDirect
(
HSTMT
hstmt
,
...
...
@@ -155,8 +152,10 @@ SQLExecDirect(
if
(
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
);
if
(
!
stmt
->
statement
)
{
...
...
@@ -170,9 +169,11 @@ SQLExecDirect(
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 */
/* then set the statement to finished so it can be recycled. */
/*
* If an SQLPrepare was performed prior to this, but was left in
* 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
)
stmt
->
status
=
STMT_FINISHED
;
...
...
@@ -195,7 +196,8 @@ SQLExecDirect(
return
result
;
}
/* Execute a prepared SQL statement */
/* Execute a prepared SQL statement */
RETCODE
SQL_API
SQLExecute
(
HSTMT
hstmt
)
...
...
@@ -206,7 +208,6 @@ SQLExecute(
int
i
,
retval
;
mylog
(
"%s: entering...
\n
"
,
func
);
if
(
!
stmt
)
...
...
@@ -280,7 +281,6 @@ SQLExecute(
if
((
stmt
->
prepare
&&
stmt
->
status
!=
STMT_READY
)
||
(
stmt
->
status
!=
STMT_ALLOCATED
&&
stmt
->
status
!=
STMT_READY
))
{
stmt
->
errornumber
=
STMT_STATUS_ERROR
;
stmt
->
errormsg
=
"The handle does not point to a statement that is ready to be executed"
;
SC_log_error
(
func
,
""
,
stmt
);
...
...
@@ -288,7 +288,6 @@ SQLExecute(
return
SQL_ERROR
;
}
/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
if
(
!
stmt
->
pre_executing
)
{
...
...
@@ -336,15 +335,10 @@ SQLExecute(
mylog
(
" stmt_with_params = '%s'
\n
"
,
stmt
->
stmt_with_params
);
return
SC_execute
(
stmt
);
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLTransact
(
HENV
henv
,
...
...
@@ -380,7 +374,6 @@ SQLTransact(
if
(
conn
&&
conn
->
henv
==
henv
)
if
(
SQLTransact
(
henv
,
(
HDBC
)
conn
,
fType
)
!=
SQL_SUCCESS
)
return
SQL_ERROR
;
}
return
SQL_SUCCESS
;
}
...
...
@@ -388,15 +381,9 @@ SQLTransact(
conn
=
(
ConnectionClass
*
)
hdbc
;
if
(
fType
==
SQL_COMMIT
)
{
stmt_string
=
"COMMIT"
;
}
else
if
(
fType
==
SQL_ROLLBACK
)
{
stmt_string
=
"ROLLBACK"
;
}
else
{
conn
->
errornumber
=
CONN_INVALID_ARGUMENT_NO
;
...
...
@@ -408,7 +395,6 @@ SQLTransact(
/* If manual commit and in transaction, then proceed. */
if
(
!
CC_is_in_autocommit
(
conn
)
&&
CC_is_in_trans
(
conn
))
{
mylog
(
"SQLTransact: sending on conn %d '%s'
\n
"
,
conn
,
stmt_string
);
res
=
CC_send_query
(
conn
,
stmt_string
,
NULL
);
...
...
@@ -433,7 +419,6 @@ SQLTransact(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLCancel
(
...
...
@@ -464,8 +449,6 @@ SQLCancel(
*/
if
(
stmt
->
data_at_exec
<
0
)
{
/*
* MAJOR HACK for Windows to reset the driver manager's cursor
* state: Because of what seems like a bug in the Odbc driver
...
...
@@ -507,14 +490,14 @@ SQLCancel(
stmt
->
put_data
=
FALSE
;
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
/* Returns the SQL string as modified by the driver. */
/* Currently, just copy the input string without modification */
/* observing buffer limits and truncation. */
/*
* Returns the SQL string as modified by the driver.
* Currently, just copy the input string without modification
* observing buffer limits and truncation.
*/
RETCODE
SQL_API
SQLNativeSql
(
HDBC
hdbc
,
...
...
@@ -564,11 +547,11 @@ SQLNativeSql(
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
SQLParamData
(
HSTMT
hstmt
,
...
...
@@ -636,11 +619,9 @@ SQLParamData(
CC_set_no_trans
(
stmt
->
hdbc
);
}
stmt
->
lobj_fd
=
-
1
;
}
/* Done, now copy the params and then execute the statement */
if
(
stmt
->
data_at_exec
==
0
)
{
...
...
@@ -675,11 +656,11 @@ SQLParamData(
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
SQLPutData
(
HSTMT
hstmt
,
...
...
@@ -701,7 +682,6 @@ SQLPutData(
return
SQL_INVALID_HANDLE
;
}
if
(
stmt
->
current_exec_param
<
0
)
{
stmt
->
errornumber
=
STMT_SEQUENCE_ERROR
;
...
...
@@ -714,7 +694,6 @@ SQLPutData(
if
(
!
stmt
->
put_data
)
{
/* first call */
mylog
(
"SQLPutData: (1) cbValue = %d
\n
"
,
cbValue
);
stmt
->
put_data
=
TRUE
;
...
...
@@ -733,11 +712,9 @@ SQLPutData(
if
(
cbValue
==
SQL_NULL_DATA
)
return
SQL_SUCCESS
;
/* Handle Long Var Binary with Large Objects */
if
(
current_param
->
SQLType
==
SQL_LONGVARBINARY
)
{
/* begin transaction if needed */
if
(
!
CC_is_in_trans
(
stmt
->
hdbc
))
{
...
...
@@ -775,8 +752,10 @@ SQLPutData(
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
*
)
&
current_param
->
lobj_oid
;
/* store the fd */
...
...
@@ -791,11 +770,10 @@ SQLPutData(
retval
=
lo_write
(
stmt
->
hdbc
,
stmt
->
lobj_fd
,
rgbValue
,
cbValue
);
mylog
(
"lo_write: cbValue=%d, wrote %d bytes
\n
"
,
cbValue
,
retval
);
}
else
{
/* for handling fields */
{
/* for handling fields */
if
(
cbValue
==
SQL_NTS
)
{
current_param
->
EXEC_buffer
=
strdup
(
rgbValue
);
...
...
@@ -841,25 +819,21 @@ SQLPutData(
}
}
}
else
{
/* calling SQLPutData more than once */
{
/* calling SQLPutData more than once */
mylog
(
"SQLPutData: (>1) cbValue = %d
\n
"
,
cbValue
);
if
(
current_param
->
SQLType
==
SQL_LONGVARBINARY
)
{
/* the large object fd is in EXEC_buffer */
retval
=
lo_write
(
stmt
->
hdbc
,
stmt
->
lobj_fd
,
rgbValue
,
cbValue
);
mylog
(
"lo_write(2): cbValue = %d, wrote %d bytes
\n
"
,
cbValue
,
retval
);
*
current_param
->
EXEC_used
+=
cbValue
;
}
else
{
buffer
=
current_param
->
EXEC_buffer
;
if
(
cbValue
==
SQL_NTS
)
...
...
@@ -880,11 +854,9 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param
->
EXEC_buffer
=
buffer
;
}
else
if
(
cbValue
>
0
)
{
old_pos
=
*
current_param
->
EXEC_used
;
*
current_param
->
EXEC_used
+=
cbValue
;
...
...
@@ -906,17 +878,14 @@ SQLPutData(
/* reassign buffer incase realloc moved it */
current_param
->
EXEC_buffer
=
buffer
;
}
else
{
SC_log_error
(
func
,
"bad cbValue"
,
stmt
);
return
SQL_ERROR
;
}
}
}
return
SQL_SUCCESS
;
}
src/interfaces/odbc/gpps.c
View file @
296e7ba2
/* GetPrivateProfileString()
/*-------
* GetPrivateProfileString()
*
* approximate implementation of
* Windows NT System Services version of GetPrivateProfileString()
...
...
@@ -15,6 +16,7 @@
* are allowed (that is an anachronism anyway)
* Added code to search for ODBC_INI file in users home directory on
* Unix
*-------
*/
#ifndef WIN32
...
...
@@ -46,7 +48,7 @@
DWORD
GetPrivateProfileString
(
char
*
theSection
,
/* section name */
char
*
theKey
,
/* search key name */
char
*
theKey
,
/* search key name */
char
*
theDefault
,
/* default value if not
* found */
char
*
theReturnBuffer
,
/* return value stored
...
...
@@ -110,7 +112,6 @@ GetPrivateProfileString(char *theSection, /* section name */
aFile
=
(
FILE
*
)
(
buf
?
fopen
(
buf
,
PG_BINARY_R
)
:
NULL
);
}
aLength
=
(
theDefault
==
NULL
)
?
0
:
strlen
(
theDefault
);
if
(
theReturnBufferLength
==
0
||
theReturnBuffer
==
NULL
)
...
...
@@ -123,7 +124,6 @@ GetPrivateProfileString(char *theSection, /* section name */
if
(
aFile
==
NULL
)
{
/* no ini file specified, return the default */
++
aLength
;
/* room for NULL char */
aLength
=
theReturnBufferLength
<
aLength
?
theReturnBufferLength
:
aLength
;
...
...
@@ -132,7 +132,6 @@ GetPrivateProfileString(char *theSection, /* section name */
return
aLength
-
1
;
}
while
(
fgets
(
aLine
,
sizeof
(
aLine
),
aFile
)
!=
NULL
)
{
aLineLength
=
strlen
(
aLine
);
...
...
@@ -147,7 +146,6 @@ GetPrivateProfileString(char *theSection, /* section name */
break
;
case
'['
:
/* section marker */
if
((
aString
=
strchr
(
aLine
,
']'
)))
{
aStart
=
aLine
+
1
;
...
...
@@ -159,30 +157,25 @@ GetPrivateProfileString(char *theSection, /* section name */
*
(
aString
+
1
)
=
'\0'
;
/* accept as matched if NULL key or exact match */
if
(
!
theSection
||
!
strcmp
(
aStart
,
theSection
))
aSectionFound
=
TRUE
;
else
aSectionFound
=
FALSE
;
}
break
;
default:
/* try to match value keys if in proper section */
if
(
aSectionFound
)
{
/* try to match requested key */
if
((
aString
=
aValue
=
strchr
(
aLine
,
'='
)))
{
*
aValue
=
'\0'
;
++
aValue
;
/* strip leading blanks in value field */
while
(
*
aValue
==
' '
&&
aValue
<
aLine
+
sizeof
(
aLine
))
*
aValue
++
=
'\0'
;
if
(
aValue
>=
aLine
+
sizeof
(
aLine
))
...
...
@@ -196,7 +189,6 @@ GetPrivateProfileString(char *theSection, /* section name */
aStart
++
;
/* strip trailing blanks from key */
if
(
aString
)
{
while
(
--
aString
>=
aStart
&&
*
aString
==
' '
)
...
...
@@ -204,16 +196,13 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* see if key is matched */
if
(
theKey
==
NULL
||
!
strcmp
(
theKey
,
aStart
))
{
/* matched -- first, terminate value part */
aKeyFound
=
TRUE
;
aLength
=
strlen
(
aValue
);
/* remove trailing blanks from aValue if any */
aString
=
aValue
+
aLength
-
1
;
while
(
--
aString
>
aValue
&&
*
aString
==
' '
)
...
...
@@ -223,7 +212,6 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* unquote value if quoted */
if
(
aLength
>=
2
&&
aValue
[
0
]
==
'"'
&&
aValue
[
aLength
-
1
]
==
'"'
)
{
...
...
@@ -236,7 +224,6 @@ GetPrivateProfileString(char *theSection, /* section name */
else
{
/* single quotes allowed also... */
if
(
aLength
>=
2
&&
aValue
[
0
]
==
'\''
&&
aValue
[
aLength
-
1
]
==
'\''
)
{
...
...
@@ -247,13 +234,11 @@ GetPrivateProfileString(char *theSection, /* section name */
}
/* compute maximum length copyable */
aLineLength
=
(
aLength
<
theReturnBufferLength
-
aReturnLength
)
?
aLength
:
theReturnBufferLength
-
aReturnLength
;
/* do the copy to return buffer */
if
(
aLineLength
)
{
strncpy
(
&
theReturnBuffer
[
aReturnLength
],
...
...
@@ -270,11 +255,9 @@ GetPrivateProfileString(char *theSection, /* section name */
fclose
(
aFile
);
aFile
=
NULL
;
}
return
aReturnLength
>
0
?
aReturnLength
-
1
:
0
;
}
}
break
;
}
}
...
...
@@ -283,7 +266,8 @@ GetPrivateProfileString(char *theSection, /* section name */
fclose
(
aFile
);
if
(
!
aKeyFound
)
{
/* key wasn't found return default */
{
/* key wasn't found return default */
++
aLength
;
/* room for NULL char */
aLength
=
theReturnBufferLength
<
aLength
?
theReturnBufferLength
:
aLength
;
...
...
@@ -294,9 +278,10 @@ GetPrivateProfileString(char *theSection, /* section name */
return
aReturnLength
>
0
?
aReturnLength
-
1
:
0
;
}
DWORD
WritePrivateProfileString
(
char
*
theSection
,
/* section name */
char
*
theKey
,
/* write key name */
char
*
theKey
,
/* write key name */
char
*
theBuffer
,
/* input buffer */
char
*
theIniFileName
)
/* pathname of ini file to
* write */
...
...
@@ -304,14 +289,16 @@ WritePrivateProfileString(char *theSection, /* section name */
return
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
* I find out different.
*/
DWORD
WritePrivateProfileString(char *theSection, /* section name */
char *theKey, /* write key name */
char *theKey,
/* write key name */
char *theBuffer, /* input buffer */
char *theIniFileName) /* pathname of ini file to
* write */
...
...
@@ -353,11 +340,12 @@ WritePrivateProfileString(char *theSection, /* section name */
if (ptr == NULL || *ptr == '\0')
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 */
/* the file won't be found and thus the default value will be */
/* returned. */
/* */
/*
* This doesn't make it so we find an ini file but allows normal
* processing to continue further on down. The likelihood is that
* 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))
...
...
@@ -368,9 +356,10 @@ WritePrivateProfileString(char *theSection, /* section name */
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);
if (!aFile)
{
...
...
@@ -380,13 +369,13 @@ WritePrivateProfileString(char *theSection, /* section name */
return 0;
}
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 just write a new line to the file. */
/* */
/*
* We have to search for theKey, because if it already
* 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)
{
aLineLength = strlen(aLine);
...
...
@@ -401,7 +390,6 @@ WritePrivateProfileString(char *theSection, /* section name */
break;
case '[': /* section marker */
if ((aString = strchr(aLine, ']')))
{
*aString = '\0';
...
...
@@ -411,13 +399,10 @@ WritePrivateProfileString(char *theSection, /* section name */
if (!strcmp(aLine + 1, theSection))
aSectionFound = TRUE;
}
break;
default:
/* try to match value keys if in proper section */
if (aSectionFound)
{
/* try to match requested key */
...
...
@@ -428,7 +413,6 @@ WritePrivateProfileString(char *theSection, /* section name */
++aValue;
/* strip leading blanks in value field */
while (*aValue == ' ' && aValue < aLine + sizeof(aLine))
*aValue++ = '\0';
if (aValue >= aLine + sizeof(aLine))
...
...
@@ -438,7 +422,6 @@ WritePrivateProfileString(char *theSection, /* section name */
aValue = "";
/* strip trailing blanks from key */
if (aString)
{
while (--aString >= aLine && *aString == ' ')
...
...
@@ -446,7 +429,6 @@ WritePrivateProfileString(char *theSection, /* section name */
}
/* see if key is matched */
if (!strcmp(theKey, aLine))
{
keyFound = TRUE;
...
...
@@ -460,7 +442,6 @@ WritePrivateProfileString(char *theSection, /* section name */
}
}
}
break;
}
}
...
...
src/interfaces/odbc/info.c
View file @
296e7ba2
/* Module: info.c
/*--------
* Module: info.c
*
* Description: This module contains routines related to
* ODBC informational functions.
...
...
@@ -12,7 +13,7 @@
* SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -56,8 +57,6 @@
extern
GLOBAL_VALUES
globals
;
/* - - - - - - - - - */
RETCODE
SQL_API
SQLGetInfo
(
HDBC
hdbc
,
...
...
@@ -154,7 +153,6 @@ SQLGetInfo(
break
;
case
SQL_CORRELATION_NAME
:
/* ODBC 1.0 */
/*
* Saying no correlation name makes Query not work right.
* value = SQL_CN_NONE;
...
...
@@ -182,11 +180,10 @@ SQLGetInfo(
break
;
case
SQL_DATABASE_NAME
:
/* Support for old ODBC 1.0 Apps */
/*
* Returning the database name causes problems in MS Query. It
* generates query like: "SELECT DISTINCT a FROM byronn
crap
3
*
crap
3"
* generates query like: "SELECT DISTINCT a FROM byronn
bad
3
*
bad
3"
*
* p = CC_get_database(conn);
*/
...
...
@@ -198,7 +195,6 @@ SQLGetInfo(
break
;
case
SQL_DBMS_VER
:
/* ODBC 1.0 */
/*
* The ODBC spec wants ##.##.#### ...whatever... so prepend
* the driver
...
...
@@ -256,7 +252,6 @@ SQLGetInfo(
break
;
case
SQL_IDENTIFIER_CASE
:
/* ODBC 1.0 */
/*
* are identifiers case-sensitive (yes, but only when quoted.
* If not quoted, they default to lowercase)
...
...
@@ -275,7 +270,6 @@ SQLGetInfo(
break
;
case
SQL_LIKE_ESCAPE_CLAUSE
:
/* ODBC 2.0 */
/*
* is there a character that escapes '%' and '_' in a LIKE
* clause? not as far as I can tell
...
...
@@ -356,18 +350,18 @@ SQLGetInfo(
case
SQL_MAX_ROW_SIZE
:
/* ODBC 2.0 */
len
=
4
;
if
(
PG_VERSION_GE
(
conn
,
7
.
1
))
{
/* Large Rowa in 7.1+ */
{
/* Large Rowa in 7.1+ */
value
=
MAX_ROW_SIZE
;
}
else
{
/* Without the Toaster we're limited to
*
the blocksize */
{
/* Without the Toaster we're limited to
the blocksize */
value
=
BLCKSZ
;
}
break
;
case
SQL_MAX_ROW_SIZE_INCLUDES_LONG
:
/* ODBC 2.0 */
/*
* does the preceding value include LONGVARCHAR and
* LONGVARBINARY fields? Well, it does include longvarchar,
...
...
@@ -379,15 +373,14 @@ SQLGetInfo(
case
SQL_MAX_STATEMENT_LEN
:
/* ODBC 2.0 */
/* maybe this should be 0? */
len
=
4
;
/* Long Queries in 7.0+ */
if
(
PG_VERSION_GE
(
conn
,
7
.
0
))
{
/* Long Queries in 7.0+ */
value
=
MAX_STATEMENT_LEN
;
}
else
if
(
PG_VERSION_GE
(
conn
,
6
.
5
))
/* Prior to 7.0 we used
* 2*BLCKSZ */
/* Prior to 7.0 we used 2*BLCKSZ */
else
if
(
PG_VERSION_GE
(
conn
,
6
.
5
))
value
=
(
2
*
BLCKSZ
);
else
/* Prior to 6.5 we used BLCKSZ */
/* Prior to 6.5 we used BLCKSZ */
value
=
BLCKSZ
;
break
;
...
...
@@ -417,9 +410,8 @@ SQLGetInfo(
break
;
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
*/
p
=
"N"
;
...
...
@@ -463,7 +455,8 @@ SQLGetInfo(
case
SQL_OJ_CAPABILITIES
:
/* ODBC 2.01 */
len
=
4
;
if
(
PG_VERSION_GE
(
conn
,
7
.
1
))
{
/* OJs in 7.1+ */
{
/* OJs in 7.1+ */
value
=
(
SQL_OJ_LEFT
|
SQL_OJ_RIGHT
|
SQL_OJ_FULL
|
...
...
@@ -473,9 +466,8 @@ SQLGetInfo(
SQL_OJ_ALL_COMPARISON_OPS
);
}
else
{
/* OJs not in <7.1 */
/* OJs not in <7.1 */
value
=
0
;
}
break
;
case
SQL_ORDER_BY_COLUMNS_IN_SELECT
:
/* ODBC 2.0 */
...
...
@@ -484,13 +476,11 @@ SQLGetInfo(
case
SQL_OUTER_JOINS
:
/* ODBC 1.0 */
if
(
PG_VERSION_GE
(
conn
,
7
.
1
))
{
/* OJs in 7.1+ */
/* OJs in 7.1+ */
p
=
"Y"
;
}
else
{
/* OJs not in <7.1 */
/* OJs not in <7.1 */
p
=
"N"
;
}
break
;
case
SQL_OWNER_TERM
:
/* ODBC 1.0 */
...
...
@@ -547,7 +537,6 @@ SQLGetInfo(
break
;
case
SQL_ROW_UPDATES
:
/* ODBC 1.0 */
/*
* Driver doesn't support keyset-driven or mixed cursors, so
* not much point in saying row updates are supported
...
...
@@ -635,7 +624,6 @@ SQLGetInfo(
break
;
case
SQL_TXN_CAPABLE
:
/* ODBC 1.0 */
/*
* Postgres can deal with create or drop table statements in a
* transaction
...
...
@@ -677,7 +665,8 @@ SQLGetInfo(
* what length would be required if a real buffer had been passed in.
*/
if
(
p
)
{
/* char/binary data */
{
/* char/binary data */
len
=
strlen
(
p
);
if
(
rgbInfoValue
)
...
...
@@ -692,13 +681,11 @@ SQLGetInfo(
}
}
}
else
{
/* numeric data */
{
/* numeric data */
if
(
rgbInfoValue
)
{
if
(
len
==
2
)
*
((
WORD
*
)
rgbInfoValue
)
=
(
WORD
)
value
;
else
if
(
len
==
4
)
...
...
@@ -712,8 +699,6 @@ SQLGetInfo(
return
result
;
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLGetTypeInfo
(
...
...
@@ -725,7 +710,7 @@ SQLGetTypeInfo(
TupleNode
*
row
;
int
i
;
/* Int4 type; */
/* Int4 type; */
Int4
pgType
;
Int2
sqlType
;
...
...
@@ -737,7 +722,6 @@ SQLGetTypeInfo(
return
SQL_INVALID_HANDLE
;
}
stmt
->
manual_result
=
TRUE
;
stmt
->
result
=
QR_Constructor
();
if
(
!
stmt
->
result
)
...
...
@@ -801,7 +785,6 @@ SQLGetTypeInfo(
}
}
stmt
->
status
=
STMT_FINISHED
;
stmt
->
currTuple
=
-
1
;
stmt
->
rowset_start
=
-
1
;
...
...
@@ -810,7 +793,6 @@ SQLGetTypeInfo(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLGetFunctions
(
...
...
@@ -824,7 +806,6 @@ SQLGetFunctions(
if
(
fFunction
==
SQL_API_ALL_FUNCTIONS
)
{
if
(
globals
.
lie
)
{
int
i
;
...
...
@@ -910,13 +891,10 @@ SQLGetFunctions(
}
else
{
if
(
globals
.
lie
)
*
pfExists
=
TRUE
;
else
{
switch
(
fFunction
)
{
case
SQL_API_SQLALLOCCONNECT
:
...
...
@@ -1094,12 +1072,10 @@ SQLGetFunctions(
}
}
}
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLTables
(
HSTMT
hstmt
,
...
...
@@ -1161,13 +1137,12 @@ SQLTables(
}
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
))
{
/* 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"
);
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 relname like '%.*s'"
,
szTableName
,
cbTableName
);
/* Parse the extra systable prefix */
strcpy
(
prefixes
,
globals
.
extra_systable_prefixes
);
i
=
0
;
prefix
[
i
]
=
strtok
(
prefixes
,
";"
);
while
(
prefix
[
i
]
&&
i
<
32
)
{
prefix
[
++
i
]
=
strtok
(
NULL
,
";"
);
}
/* Parse the desired table types to return */
show_system_tables
=
FALSE
;
...
...
@@ -1216,7 +1188,6 @@ SQLTables(
show_regular_tables
=
TRUE
;
else
if
(
strstr
(
table_type
[
i
],
"VIEW"
))
show_views
=
TRUE
;
i
++
;
}
}
...
...
@@ -1243,21 +1214,17 @@ SQLTables(
strcat
(
tables_query
,
prefix
[
i
]);
i
++
;
}
strcat
(
tables_query
,
"'"
);
}
/* match users */
if
(
PG_VERSION_LT
(
conn
,
7
.
1
))
/* filter out large objects in
*
older versions */
if
(
PG_VERSION_LT
(
conn
,
7
.
1
))
/* filter out large objects in
older versions */
strcat
(
tables_query
,
" and relname !~ '^xinv[0-9]+'"
);
strcat
(
tables_query
,
" and usesysid = relowner"
);
strcat
(
tables_query
,
" order by relname"
);
/* ********************************************************************** */
result
=
SQLExecDirect
(
htbl_stmt
,
tables_query
,
strlen
(
tables_query
));
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
{
...
...
@@ -1330,7 +1297,6 @@ SQLTables(
result
=
SQLFetch
(
htbl_stmt
);
while
((
result
==
SQL_SUCCESS
)
||
(
result
==
SQL_SUCCESS_WITH_INFO
))
{
/*
* Determine if this table name is a system table. If treating
* system tables as regular tables, then no need to do this test.
...
...
@@ -1338,12 +1304,12 @@ SQLTables(
systable
=
FALSE
;
if
(
!
atoi
(
ci
->
show_system_tables
))
{
if
(
strncmp
(
table_name
,
POSTGRES_SYS_PREFIX
,
strlen
(
POSTGRES_SYS_PREFIX
))
==
0
)
systable
=
TRUE
;
else
{
/* Check extra system table prefixes */
{
/* Check extra system table prefixes */
i
=
0
;
while
(
prefix
[
i
])
{
...
...
@@ -1359,8 +1325,8 @@ SQLTables(
}
/* Determine if the table name is a view */
if
(
PG_VERSION_GE
(
conn
,
7
.
1
))
/* view is represented by its
*
relkind since 7.1 */
if
(
PG_VERSION_GE
(
conn
,
7
.
1
))
/* view is represented by its
relkind since 7.1 */
view
=
(
relkind_or_hasrules
[
0
]
==
'v'
);
else
view
=
(
relkind_or_hasrules
[
0
]
==
'1'
);
...
...
@@ -1379,16 +1345,18 @@ SQLTables(
(
view
&&
show_views
)
||
(
regular_table
&&
show_regular_tables
))
{
row
=
(
TupleNode
*
)
malloc
(
sizeof
(
TupleNode
)
+
(
5
-
1
)
*
sizeof
(
TupleField
));
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'. */
/* (this is valid according to the ODBC SQL grammar, but */
/* Postgres won't support it.) */
/* set_tuplefield_string(&row->tuple[1], table_owner); */
/*
* I have to hide the table owner from Access, otherwise it
* insists on referring to the table as 'owner.table'.
* (this is valid according to the ODBC SQL grammar, but
* Postgres won't support it.)
*
* set_tuplefield_string(&row->tuple[1], table_owner);
*/
mylog
(
"SQLTables: table_name = '%s'
\n
"
,
table_name
);
...
...
@@ -1410,8 +1378,10 @@ SQLTables(
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
;
/* set up the current tuple pointer for SQLFetch */
...
...
@@ -1425,8 +1395,6 @@ SQLTables(
}
RETCODE
SQL_API
SQLColumns
(
HSTMT
hstmt
,
...
...
@@ -1479,13 +1447,10 @@ SQLColumns(
conn
=
(
ConnectionClass
*
)
(
stmt
->
hdbc
);
ci
=
&
stmt
->
hdbc
->
connInfo
;
/* ********************************************************************** */
/*
* Create the query to find out the columns (Note: pre 6.3 did not
* have the atttypmod field)
*/
/* ********************************************************************** */
sprintf
(
columns_query
,
"select u.usename, c.relname, a.attname, a.atttypid"
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
" 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 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"
);
/* ********************************************************************** */
result
=
SQLAllocStmt
(
stmt
->
hdbc
,
&
hcol_stmt
);
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
,
13
,
"FIELD_TYPE"
,
PG_TYPE_INT4
,
4
);
result
=
SQLFetch
(
hcol_stmt
);
/*
* 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
...
...
@@ -1685,12 +1649,10 @@ SQLColumns(
if
(
result
!=
SQL_ERROR
&&
!
stmt
->
internal
)
{
if
(
relhasrules
[
0
]
!=
'1'
&&
(
atoi
(
ci
->
show_oid_column
)
||
strncmp
(
table_name
,
POSTGRES_SYS_PREFIX
,
strlen
(
POSTGRES_SYS_PREFIX
))
==
0
))
{
/* For OID fields */
the_type
=
PG_TYPE_OID
;
row
=
(
TupleNode
*
)
malloc
(
sizeof
(
TupleNode
)
+
...
...
@@ -1718,7 +1680,6 @@ SQLColumns(
QR_add_tuple
(
stmt
->
result
,
row
);
}
}
while
((
result
==
SQL_SUCCESS
)
||
(
result
==
SQL_SUCCESS_WITH_INFO
))
...
...
@@ -1776,11 +1737,9 @@ SQLColumns(
}
}
if
((
field_type
==
PG_TYPE_VARCHAR
)
||
(
field_type
==
PG_TYPE_BPCHAR
))
{
useStaticPrecision
=
FALSE
;
if
(
mod_length
>=
4
)
...
...
@@ -1827,8 +1786,10 @@ SQLColumns(
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
))
{
/* For Row Versioning fields */
...
...
@@ -1855,8 +1816,10 @@ SQLColumns(
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
;
/* set up the current tuple pointer for SQLFetch */
...
...
@@ -1869,6 +1832,7 @@ SQLColumns(
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLSpecialColumns
(
HSTMT
hstmt
,
...
...
@@ -1892,8 +1856,6 @@ SQLSpecialColumns(
RETCODE
result
;
char
relhasrules
[
MAX_INFO_STRING
];
mylog
(
"%s: entering...stmt=%u
\n
"
,
func
,
stmt
);
if
(
!
stmt
)
...
...
@@ -1905,10 +1867,9 @@ SQLSpecialColumns(
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 "
"from pg_user u, pg_class c where "
"u.usesysid = c.relowner"
);
...
...
@@ -1988,7 +1949,6 @@ SQLSpecialColumns(
}
else
if
(
fColType
==
SQL_ROWVER
)
{
Int2
the_type
=
PG_TYPE_INT4
;
if
(
atoi
(
ci
->
row_versioning
))
...
...
@@ -2009,8 +1969,6 @@ SQLSpecialColumns(
}
}
stmt
->
status
=
STMT_FINISHED
;
stmt
->
currTuple
=
-
1
;
stmt
->
rowset_start
=
-
1
;
...
...
@@ -2020,6 +1978,7 @@ SQLSpecialColumns(
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLStatistics
(
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
,
12
,
"FILTER_CONDITION"
,
PG_TYPE_TEXT
,
MAX_INFO_STRING
);
/* only use the table name... the owner should be redundant, and */
/* we never use qualifiers. */
/*
* only use the table name... the owner should be redundant, and
* we never use qualifiers.
*/
table_name
=
make_string
(
szTableName
,
cbTableName
,
NULL
);
if
(
!
table_name
)
{
...
...
@@ -2116,8 +2076,10 @@ SQLStatistics(
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
);
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
{
...
...
@@ -2172,6 +2134,7 @@ SQLStatistics(
result
=
SQLFetch
(
hcol_stmt
);
}
if
(
result
!=
SQL_NO_DATA_FOUND
||
total_columns
==
0
)
{
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
));
if
((
result
!=
SQL_SUCCESS
)
&&
(
result
!=
SQL_SUCCESS_WITH_INFO
))
{
stmt
->
errormsg
=
SC_create_errormsg
(
hindx_stmt
);
/* "Couldn't execute
* index query
* (w/SQLExecDirect) in
* SQLStatistics."; */
/*
* "Couldn't execute index query (w/SQLExecDirect) in
* SQLStatistics.";
*/
stmt
->
errormsg
=
SC_create_errormsg
(
hindx_stmt
);
stmt
->
errornumber
=
indx_stmt
->
errornumber
;
SQLFreeStmt
(
hindx_stmt
,
SQL_DROP
);
goto
SEEYA
;
}
/* bind the index name column */
...
...
@@ -2314,7 +2278,6 @@ SQLStatistics(
result
=
SQLFetch
(
hindx_stmt
);
while
((
result
==
SQL_SUCCESS
)
||
(
result
==
SQL_SUCCESS_WITH_INFO
))
{
/* If only requesting unique indexs, then just return those. */
if
(
fUnique
==
SQL_INDEX_ALL
||
(
fUnique
==
SQL_INDEX_UNIQUE
&&
atoi
(
isunique
)))
...
...
@@ -2323,7 +2286,6 @@ SQLStatistics(
/* add a row in this table for each field in the index */
while
(
i
<
16
&&
fields_vector
[
i
]
!=
0
)
{
row
=
(
TupleNode
*
)
malloc
(
sizeof
(
TupleNode
)
+
(
13
-
1
)
*
sizeof
(
TupleField
));
...
...
@@ -2380,8 +2342,8 @@ SQLStatistics(
}
if
(
result
!=
SQL_NO_DATA_FOUND
)
{
stmt
->
errormsg
=
SC_create_errormsg
(
hindx_stmt
);
/* "SQLFetch failed in
* SQLStatistics."; */
/* "SQLFetch failed in SQLStatistics."; */
stmt
->
errormsg
=
SC_create_errormsg
(
hindx_stmt
);
stmt
->
errornumber
=
indx_stmt
->
errornumber
;
SQLFreeStmt
(
hindx_stmt
,
SQL_DROP
);
goto
SEEYA
;
...
...
@@ -2389,8 +2351,10 @@ SQLStatistics(
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
;
/* set up the current tuple pointer for SQLFetch */
...
...
@@ -2418,6 +2382,7 @@ SEEYA:
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLColumnPrivileges
(
HSTMT
hstmt
,
...
...
@@ -2434,15 +2399,17 @@ SQLColumnPrivileges(
mylog
(
"%s: entering...
\n
"
,
func
);
/* Neither Access or Borland care about this. */
/* Neither Access or Borland care about this. */
SC_log_error
(
func
,
"Function not implemented"
,
(
StatementClass
*
)
hstmt
);
return
SQL_ERROR
;
}
/* SQLPrimaryKeys()
* Retrieve the primary key columns for the specified table.
/*
* SQLPrimaryKeys()
*
* Retrieve the primary key columns for the specified table.
*/
RETCODE
SQL_API
SQLPrimaryKeys
(
...
...
@@ -2572,7 +2539,6 @@ SQLPrimaryKeys(
while
((
result
==
SQL_SUCCESS
)
||
(
result
==
SQL_SUCCESS_WITH_INFO
))
{
row
=
(
TupleNode
*
)
malloc
(
sizeof
(
TupleNode
)
+
(
result_cols
-
1
)
*
sizeof
(
TupleField
));
set_tuplefield_null
(
&
row
->
tuple
[
0
]);
...
...
@@ -2608,8 +2574,10 @@ SQLPrimaryKeys(
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
;
/* set up the current tuple pointer for SQLFetch */
...
...
@@ -2621,6 +2589,7 @@ SQLPrimaryKeys(
return
SQL_SUCCESS
;
}
RETCODE
SQL_API
SQLForeignKeys
(
HSTMT
hstmt
,
...
...
@@ -2667,14 +2636,11 @@ SQLForeignKeys(
#if (ODBCVER >= 0x0300)
SWORD
defer_type
;
#endif
char
pkey
[
MAX_INFO_STRING
];
Int2
result_cols
;
mylog
(
"%s: entering...stmt=%u
\n
"
,
func
,
stmt
);
mylog
(
"%s: entering...stmt=%u
\n
"
,
func
,
stmt
);
if
(
!
stmt
)
{
...
...
@@ -2723,8 +2689,10 @@ SQLForeignKeys(
QR_set_field_info
(
stmt
->
result
,
14
,
"DEFERRABILITY"
,
PG_TYPE_INT2
,
2
);
#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
;
/* set up the current tuple pointer for SQLFetch */
...
...
@@ -2898,7 +2866,6 @@ SQLForeignKeys(
while
(
result
==
SQL_SUCCESS
)
{
/* Compute the number of keyparts. */
num_keys
=
(
trig_nargs
-
4
)
/
2
;
...
...
@@ -2913,7 +2880,6 @@ SQLForeignKeys(
/* If there is a pk table specified, then check it. */
if
(
pk_table_needed
[
0
]
!=
'\0'
)
{
/* If it doesn't match, then continue */
if
(
strcmp
(
pk_table
,
pk_table_needed
))
{
...
...
@@ -2932,7 +2898,6 @@ SQLForeignKeys(
return
SQL_ERROR
;
}
/* Check that the key listed is the primary key */
keyresult
=
SQLFetch
(
hpkey_stmt
);
...
...
@@ -2949,7 +2914,6 @@ SQLForeignKeys(
num_keys
=
0
;
break
;
}
/* Get to next primary key */
for
(
k
=
0
;
k
<
2
;
k
++
)
pkey_ptr
+=
strlen
(
pkey_ptr
)
+
1
;
...
...
@@ -3002,7 +2966,6 @@ SQLForeignKeys(
for
(
k
=
0
;
k
<
num_keys
;
k
++
)
{
row
=
(
TupleNode
*
)
malloc
(
sizeof
(
TupleNode
)
+
(
result_cols
-
1
)
*
sizeof
(
TupleField
));
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'
)
{
sprintf
(
tables_query
,
"SELECT pg_trigger.tgargs, "
" pg_trigger.tgnargs, "
" pg_trigger.tgdeferrable, "
...
...
@@ -3172,7 +3134,6 @@ SQLForeignKeys(
while
(
result
==
SQL_SUCCESS
)
{
/* Calculate the number of key parts */
num_keys
=
(
trig_nargs
-
4
)
/
2
;;
...
...
@@ -3216,7 +3177,6 @@ SQLForeignKeys(
for
(
i
=
0
;
i
<
5
;
i
++
)
pkey_ptr
+=
strlen
(
pkey_ptr
)
+
1
;
/* Get to first foreign table */
fk_table
=
trig_args
;
fk_table
+=
strlen
(
fk_table
)
+
1
;
...
...
@@ -3228,7 +3188,6 @@ SQLForeignKeys(
for
(
k
=
0
;
k
<
num_keys
;
k
++
)
{
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
));
...
...
@@ -3270,7 +3229,6 @@ SQLForeignKeys(
fkey_ptr
+=
strlen
(
fkey_ptr
)
+
1
;
}
}
result
=
SQLFetch
(
htbl_stmt
);
}
}
...
...
@@ -3290,7 +3248,6 @@ SQLForeignKeys(
}
RETCODE
SQL_API
SQLProcedureColumns
(
HSTMT
hstmt
,
...
...
@@ -3311,6 +3268,7 @@ SQLProcedureColumns(
return
SQL_ERROR
;
}
RETCODE
SQL_API
SQLProcedures
(
HSTMT
hstmt
,
...
...
@@ -3329,6 +3287,7 @@ SQLProcedures(
return
SQL_ERROR
;
}
RETCODE
SQL_API
SQLTablePrivileges
(
HSTMT
hstmt
,
...
...
src/interfaces/odbc/lobj.c
View file @
296e7ba2
/* Module: lobj.c
/*--------
* Module: lobj.c
*
* Description: This module contains routines related to manipulating
* large objects.
...
...
@@ -8,13 +9,14 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#include "lobj.h"
#include "psqlodbc.h"
#include "connection.h"
Oid
lo_creat
(
ConnectionClass
*
conn
,
int
mode
)
{
...
...
@@ -30,18 +32,16 @@ lo_creat(ConnectionClass *conn, int mode)
return
0
;
/* invalid oid */
else
return
retval
;
}
int
lo_open
(
ConnectionClass
*
conn
,
int
lobjId
,
int
mode
)
{
int
fd
;
int
result_len
;
LO_ARG
argv
[
2
];
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
argv
[
0
].
u
.
integer
=
lobjId
;
...
...
@@ -59,6 +59,7 @@ lo_open(ConnectionClass *conn, int lobjId, int mode)
return
fd
;
}
int
lo_close
(
ConnectionClass
*
conn
,
int
fd
)
{
...
...
@@ -66,17 +67,14 @@ lo_close(ConnectionClass *conn, int fd)
int
retval
,
result_len
;
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
argv
[
0
].
u
.
integer
=
fd
;
if
(
!
CC_send_function
(
conn
,
LO_CLOSE
,
&
retval
,
&
result_len
,
1
,
argv
,
1
))
return
-
1
;
else
return
retval
;
}
...
...
@@ -86,7 +84,6 @@ lo_read(ConnectionClass *conn, int fd, char *buf, int len)
LO_ARG
argv
[
2
];
int
result_len
;
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
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
))
return
-
1
;
else
return
result_len
;
}
int
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
,
result_len
;
if
(
len
<=
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
))
return
-
1
;
else
return
retval
;
}
int
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
,
result_len
;
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
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
))
return
-
1
;
else
return
retval
;
}
int
lo_tell
(
ConnectionClass
*
conn
,
int
fd
)
{
...
...
@@ -162,18 +157,17 @@ lo_tell(ConnectionClass *conn, int fd)
int
retval
,
result_len
;
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
argv
[
0
].
u
.
integer
=
fd
;
if
(
!
CC_send_function
(
conn
,
LO_TELL
,
&
retval
,
&
result_len
,
1
,
argv
,
1
))
return
-
1
;
else
return
retval
;
}
int
lo_unlink
(
ConnectionClass
*
conn
,
Oid
lobjId
)
{
...
...
@@ -181,14 +175,12 @@ lo_unlink(ConnectionClass *conn, Oid lobjId)
int
retval
,
result_len
;
argv
[
0
].
isint
=
1
;
argv
[
0
].
len
=
4
;
argv
[
0
].
u
.
integer
=
lobjId
;
if
(
!
CC_send_function
(
conn
,
LO_UNLINK
,
&
retval
,
&
result_len
,
1
,
argv
,
1
))
return
-
1
;
else
return
retval
;
}
src/interfaces/odbc/misc.c
View file @
296e7ba2
/* Module: misc.c
/*-------
* Module: misc.c
*
* Description: This module contains miscellaneous routines
* such as for debugging/logging and string functions.
...
...
@@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#include <stdio.h>
...
...
@@ -31,6 +32,7 @@
extern
GLOBAL_VALUES
globals
;
void
generate_filename
(
char
*
,
char
*
,
char
*
);
void
generate_filename
(
char
*
dirname
,
char
*
prefix
,
char
*
filename
)
{
...
...
@@ -56,8 +58,8 @@ generate_filename(char *dirname, char *prefix, char *filename)
return
;
}
#ifdef MY_LOG
#ifdef MY_LOG
void
mylog
(
char
*
fmt
,...)
{
...
...
@@ -83,12 +85,10 @@ mylog(char *fmt,...)
va_end
(
args
);
}
}
#endif
#ifdef Q_LOG
void
qlog
(
char
*
fmt
,...)
{
...
...
@@ -114,7 +114,6 @@ qlog(char *fmt,...)
va_end
(
args
);
}
}
#endif
/* Undefine these because windows.h will redefine and cause a warning */
...
...
@@ -137,7 +136,10 @@ qlog(char *fmt,...)
#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
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
)
return
STRCPY_FAIL
;
else
{
if
(
src_len
<
dst_len
)
...
...
@@ -173,10 +174,13 @@ my_strcpy(char *dst, int dst_len, char *src, int src_len)
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 */
/* terminate the destination string. */
/*
* 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
* terminate the destination string.
*/
char
*
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
)
{
/* Just in case, check for special lengths */
if
(
len
==
SQL_NULL_DATA
)
{
...
...
@@ -204,9 +207,14 @@ strncpy_null(char *dst, const char *src, int len)
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
*
make_string
(
char
*
s
,
int
len
,
char
*
buf
)
{
...
...
@@ -234,14 +242,16 @@ make_string(char *s, int len, char *buf)
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). */
/* This routine could be modified to use vsprintf() to handle multiple arguments. */
/*
* 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).
* This routine could be modified to use vsprintf() to handle multiple arguments.
*/
char
*
my_strcat
(
char
*
buf
,
char
*
fmt
,
char
*
s
,
int
len
)
{
if
(
s
&&
(
len
>
0
||
(
len
==
SQL_NTS
&&
strlen
(
s
)
>
0
)))
{
int
length
=
(
len
>
0
)
?
len
:
strlen
(
s
);
...
...
@@ -254,6 +264,7 @@ my_strcat(char *buf, char *fmt, char *s, int len)
return
NULL
;
}
void
remove_newlines
(
char
*
string
)
{
...
...
@@ -267,6 +278,7 @@ remove_newlines(char *string)
}
}
char
*
trim
(
char
*
s
)
{
...
...
src/interfaces/odbc/multibyte.c
View file @
296e7ba2
/*
/*
--------
* Module : multibyte.c
*
* Description: Mlutibyte related additional function.
*
* Create 2001-03-03 Eiji Tokuya
*
*
--------
*/
#include <string.h>
...
...
@@ -13,6 +13,7 @@
int
multibyte_client_encoding
;
/* Multibyte Client Encoding. */
int
multibyte_status
;
/* Multibyte Odds and ends character. */
unsigned
char
*
multibyte_strchr
(
unsigned
char
*
s
,
unsigned
char
c
)
{
...
...
@@ -36,7 +37,6 @@ multibyte_strchr(unsigned char *s, unsigned char c)
}
break
;
/* Chinese Big5 Support. */
case
BIG5
:
{
...
...
@@ -59,12 +59,14 @@ multibyte_strchr(unsigned char *s, unsigned char c)
return
(
s
+
i
);
}
void
multibyte_init
(
void
)
{
multibyte_status
=
0
;
}
unsigned
char
*
check_client_encoding
(
unsigned
char
*
str
)
{
...
...
@@ -81,19 +83,21 @@ check_client_encoding(unsigned char *str)
return
(
"OHTER"
);
}
/*
/*--------
* Multibyte Status Function.
* Input char
* Output 0 : 1 Byte Character.
* 1 : MultibyteCharacter Last Byte.
* N : MultibyteCharacter Fast or Middle Byte.
*--------
*/
int
multibyte_char_check
(
unsigned
char
s
)
{
switch
(
multibyte_client_encoding
)
{
/* Japanese Shift-JIS(CP932) Support. */
/* Japanese Shift-JIS(CP932) Support. */
case
SJIS
:
{
if
(
multibyte_status
<
2
&&
s
>
0x80
&&
!
(
s
>
0x9f
&&
s
<
0xE0
))
...
...
@@ -105,20 +109,19 @@ multibyte_char_check(unsigned char s)
}
break
;
/* Chinese Big5(CP950) Support. */
case
BIG5
:
{
if
(
multibyte_status
<
2
&&
s
>
0xA0
)
multibyte_status
=
2
;
else
if
(
multibyte_status
==
2
)
multibyte_status
=
1
;
else
multibyte_status
=
0
;
}
break
;
default:
multibyte_status
=
0
;
/* Chinese Big5(CP950) Support. */
case
BIG5
:
{
if
(
multibyte_status
<
2
&&
s
>
0xA0
)
multibyte_status
=
2
;
else
if
(
multibyte_status
==
2
)
multibyte_status
=
1
;
else
multibyte_status
=
0
;
}
break
;
default:
multibyte_status
=
0
;
}
#ifdef _DEBUG
qlog
(
"multibyte_client_encoding = %d s = 0x%02X multibyte_stat = %d
\n
"
,
multibyte_client_encoding
,
s
,
multibyte_status
);
...
...
src/interfaces/odbc/options.c
View file @
296e7ba2
/* Module: options.c
/*--------
* Module: options.c
*
* Description: This module contains routines for getting/setting
* connection and statement options.
...
...
@@ -9,7 +10,7 @@
* SQLGetStmtOption
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -43,7 +44,6 @@ RETCODE set_statement_option(ConnectionClass *conn,
UDWORD
vParam
);
RETCODE
set_statement_option
(
ConnectionClass
*
conn
,
StatementClass
*
stmt
,
...
...
@@ -53,7 +53,6 @@ set_statement_option(ConnectionClass *conn,
static
char
*
func
=
"set_statement_option"
;
char
changed
=
FALSE
;
switch
(
fOption
)
{
case
SQL_ASYNC_ENABLE
:
/* ignored */
...
...
@@ -68,12 +67,10 @@ set_statement_option(ConnectionClass *conn,
break
;
case
SQL_CONCURRENCY
:
/*
* positioned update isn't supported so cursor concurrency is
* read-only
*/
if
(
conn
)
conn
->
stmtOptions
.
scroll_concurrency
=
vParam
;
if
(
stmt
)
...
...
@@ -104,7 +101,6 @@ set_statement_option(ConnectionClass *conn,
*/
case
SQL_CURSOR_TYPE
:
/*
* if declare/fetch, then type can only be forward. otherwise,
* it can only be forward or static.
...
...
@@ -113,18 +109,15 @@ set_statement_option(ConnectionClass *conn,
if
(
globals
.
lie
)
{
if
(
conn
)
conn
->
stmtOptions
.
cursor_type
=
vParam
;
if
(
stmt
)
stmt
->
options
.
cursor_type
=
vParam
;
}
else
{
if
(
globals
.
use_declarefetch
)
{
if
(
conn
)
conn
->
stmtOptions
.
cursor_type
=
SQL_CURSOR_FORWARD_ONLY
;
if
(
stmt
)
...
...
@@ -137,7 +130,6 @@ set_statement_option(ConnectionClass *conn,
{
if
(
vParam
==
SQL_CURSOR_FORWARD_ONLY
||
vParam
==
SQL_CURSOR_STATIC
)
{
if
(
conn
)
conn
->
stmtOptions
.
cursor_type
=
vParam
;
/* valid type */
if
(
stmt
)
...
...
@@ -145,7 +137,6 @@ set_statement_option(ConnectionClass *conn,
}
else
{
if
(
conn
)
conn
->
stmtOptions
.
cursor_type
=
SQL_CURSOR_STATIC
;
if
(
stmt
)
...
...
@@ -167,14 +158,20 @@ set_statement_option(ConnectionClass *conn,
break
;
/*
* if (globals.lie) stmt->keyset_size = vParam; else {
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
* stmt->errormsg = "Driver does not support keyset size
* option"; SC_log_error(func, "", stmt); return SQL_ERROR; }
/*-------
* if (globals.lie)
* stmt->keyset_size = vParam;
* else
* {
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
* stmt->errormsg = "Driver does not support keyset size option";
* SC_log_error(func, "", stmt);
* return SQL_ERROR;
* }
*-------
*/
case
SQL_MAX_LENGTH
:
/* ignored, but saved */
case
SQL_MAX_LENGTH
:
/* ignored, but saved */
mylog
(
"SetStmtOption(): SQL_MAX_LENGTH, vParam = %d
\n
"
,
vParam
);
if
(
conn
)
conn
->
stmtOptions
.
maxLength
=
vParam
;
...
...
@@ -182,7 +179,7 @@ set_statement_option(ConnectionClass *conn,
stmt
->
options
.
maxLength
=
vParam
;
break
;
case
SQL_MAX_ROWS
:
/* ignored, but saved */
case
SQL_MAX_ROWS
:
/* ignored, but saved */
mylog
(
"SetStmtOption(): SQL_MAX_ROWS, vParam = %d
\n
"
,
vParam
);
if
(
conn
)
conn
->
stmtOptions
.
maxRows
=
vParam
;
...
...
@@ -190,16 +187,16 @@ set_statement_option(ConnectionClass *conn,
stmt
->
options
.
maxRows
=
vParam
;
break
;
case
SQL_NOSCAN
:
/* ignored */
case
SQL_NOSCAN
:
/* ignored */
mylog
(
"SetStmtOption: SQL_NOSCAN, vParam = %d
\n
"
,
vParam
);
break
;
case
SQL_QUERY_TIMEOUT
:
/* ignored */
case
SQL_QUERY_TIMEOUT
:
/* ignored */
mylog
(
"SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d
\n
"
,
vParam
);
/* "0" returned in SQLGetStmtOption */
break
;
case
SQL_RETRIEVE_DATA
:
/* ignored, but saved */
case
SQL_RETRIEVE_DATA
:
/* ignored, but saved */
mylog
(
"SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d
\n
"
,
vParam
);
if
(
conn
)
conn
->
stmtOptions
.
retrieve_data
=
vParam
;
...
...
@@ -210,7 +207,6 @@ set_statement_option(ConnectionClass *conn,
case
SQL_ROWSET_SIZE
:
mylog
(
"SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d
\n
"
,
vParam
);
/*
* Save old rowset size for SQLExtendedFetch purposes If the
* 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
;
if
(
stmt
)
stmt
->
options
.
rowset_size
=
vParam
;
break
;
case
SQL_SIMULATE_CURSOR
:
/* NOT SUPPORTED */
...
...
@@ -249,7 +244,6 @@ set_statement_option(ConnectionClass *conn,
return
SQL_ERROR
;
case
SQL_USE_BOOKMARKS
:
if
(
stmt
)
stmt
->
options
.
use_bookmarks
=
vParam
;
if
(
conn
)
...
...
@@ -298,7 +292,6 @@ set_statement_option(ConnectionClass *conn,
}
/* Implements only SQL_AUTOCOMMIT */
RETCODE
SQL_API
SQLSetConnectOption
(
...
...
@@ -320,14 +313,12 @@ SQLSetConnectOption(
return
SQL_INVALID_HANDLE
;
}
switch
(
fOption
)
{
/*
* Statement Options (apply to all stmts on the connection and
* become defaults for new stmts)
*/
/*
* Statement Options (apply to all stmts on the connection and
* become defaults for new stmts)
*/
case
SQL_ASYNC_ENABLE
:
case
SQL_BIND_TYPE
:
case
SQL_CONCURRENCY
:
...
...
@@ -362,15 +353,14 @@ SQLSetConnectOption(
break
;
/**********************************/
/***** Connection Options *******/
/*********************************
*/
/*
* Connection Options
*/
case
SQL_ACCESS_MODE
:
/* ignored */
break
;
case
SQL_AUTOCOMMIT
:
if
(
CC_is_in_trans
(
conn
))
{
conn
->
errormsg
=
"Cannot switch commit mode while a transaction is in progress"
;
...
...
@@ -397,13 +387,12 @@ SQLSetConnectOption(
CC_log_error
(
func
,
""
,
conn
);
return
SQL_ERROR
;
}
break
;
case
SQL_CURRENT_QUALIFIER
:
/* ignored */
break
;
case
SQL_LOGIN_TIMEOUT
:
/* ignored */
case
SQL_LOGIN_TIMEOUT
:
/* ignored */
break
;
case
SQL_PACKET_SIZE
:
/* ignored */
...
...
@@ -412,10 +401,10 @@ SQLSetConnectOption(
case
SQL_QUIET_MODE
:
/* ignored */
break
;
case
SQL_TXN_ISOLATION
:
/* ignored */
case
SQL_TXN_ISOLATION
:
/* ignored */
break
;
/* These options should be handled by driver manager */
/* These options should be handled by driver manager */
case
SQL_ODBC_CURSORS
:
case
SQL_OPT_TRACE
:
case
SQL_OPT_TRACEFILE
:
...
...
@@ -434,7 +423,6 @@ SQLSetConnectOption(
CC_log_error
(
func
,
option
,
conn
);
return
SQL_ERROR
;
}
}
if
(
changed
)
...
...
@@ -447,7 +435,6 @@ SQLSetConnectOption(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
/* This function just can tell you whether you are in Autcommit mode or not */
RETCODE
SQL_API
...
...
@@ -469,7 +456,7 @@ SQLGetConnectOption(
switch
(
fOption
)
{
case
SQL_ACCESS_MODE
:
/* NOT SUPPORTED */
case
SQL_ACCESS_MODE
:
/* NOT SUPPORTED */
*
((
UDWORD
*
)
pvParam
)
=
SQL_MODE_READ_WRITE
;
break
;
...
...
@@ -484,23 +471,23 @@ SQLGetConnectOption(
break
;
case
SQL_LOGIN_TIMEOUT
:
/* NOT SUPPORTED */
case
SQL_LOGIN_TIMEOUT
:
/* NOT SUPPORTED */
*
((
UDWORD
*
)
pvParam
)
=
0
;
break
;
case
SQL_PACKET_SIZE
:
/* NOT SUPPORTED */
case
SQL_PACKET_SIZE
:
/* NOT SUPPORTED */
*
((
UDWORD
*
)
pvParam
)
=
globals
.
socket_buffersize
;
break
;
case
SQL_QUIET_MODE
:
/* NOT SUPPORTED */
case
SQL_QUIET_MODE
:
/* NOT SUPPORTED */
*
((
UDWORD
*
)
pvParam
)
=
(
UDWORD
)
NULL
;
break
;
case
SQL_TXN_ISOLATION
:
/* NOT SUPPORTED */
case
SQL_TXN_ISOLATION
:
/* NOT SUPPORTED */
*
((
UDWORD
*
)
pvParam
)
=
SQL_TXN_SERIALIZABLE
;
break
;
/* These options should be handled by driver manager */
/* These options should be handled by driver manager */
case
SQL_ODBC_CURSORS
:
case
SQL_OPT_TRACE
:
case
SQL_OPT_TRACEFILE
:
...
...
@@ -520,13 +507,11 @@ SQLGetConnectOption(
return
SQL_ERROR
;
break
;
}
}
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLSetStmtOption
(
...
...
@@ -539,10 +524,11 @@ SQLSetStmtOption(
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 */
/* and expects the driver to reduce it to the real value */
/*
* Though 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
* and expects the driver to reduce it to the real value.
*/
if
(
!
stmt
)
{
SC_log_error
(
func
,
""
,
NULL
);
...
...
@@ -553,8 +539,6 @@ SQLSetStmtOption(
}
/* - - - - - - - - - */
RETCODE
SQL_API
SQLGetStmtOption
(
HSTMT
hstmt
,
...
...
@@ -567,10 +551,11 @@ SQLGetStmtOption(
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 */
/* and expects the driver to reduce it to the real value */
/*
* 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
* and expects the driver to reduce it to the real value
*/
if
(
!
stmt
)
{
SC_log_error
(
func
,
""
,
NULL
);
...
...
@@ -689,5 +674,3 @@ SQLGetStmtOption(
return
SQL_SUCCESS
;
}
/* - - - - - - - - - */
src/interfaces/odbc/parse.c
View file @
296e7ba2
/* Module: parse.c
/*--------
* Module: parse.c
*
* Description: This module contains routines related to parsing SQL
statements.
* This can be useful for two reasons:
* Description: This module contains routines related to parsing SQL
*
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.
* in the functions SQLDescribeCol and SQLColAttributes. Currently, Postgres
* doesn't return any information about these things in a query.
* 2. To be able to return information about precision,
* nullability, aliases, etc. in the functions
* SQLDescribeCol and SQLColAttributes. Currently,
* Postgres doesn't return any information about
* these things in a query.
*
* Classes: none
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
/* 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
);
char
searchColInfo
(
COL_INFO
*
col_info
,
FIELD_INFO
*
fi
);
char
*
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
]
!=
','
&&
s
[
i
]
!=
'\0'
&&
out
!=
smax
)
{
/* Handle quoted stuff */
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
));
}
char
searchColInfo
(
COL_INFO
*
col_info
,
FIELD_INFO
*
fi
)
{
int
k
,
cmp
;
char
*
col
;
for
(
k
=
0
;
k
<
QR_get_num_tuples
(
col_info
->
result
);
k
++
)
{
col
=
QR_get_value_manual
(
col_info
->
result
,
k
,
3
);
...
...
@@ -289,7 +293,6 @@ parse_statement(StatementClass *stmt)
StatementClass
*
col_stmt
;
RETCODE
result
;
mylog
(
"%s: entering...
\n
"
,
func
);
ptr
=
stmt
->
statement
;
...
...
@@ -301,7 +304,6 @@ parse_statement(StatementClass *stmt)
while
((
ptr
=
getNextToken
(
ptr
,
token
,
sizeof
(
token
),
&
delim
,
&
quote
,
&
dquote
,
&
numeric
))
!=
NULL
)
{
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
);
...
...
@@ -345,7 +347,6 @@ parse_statement(StatementClass *stmt)
!
stricmp
(
token
,
"group"
)
||
!
stricmp
(
token
,
"having"
)))
{
in_select
=
FALSE
;
in_from
=
FALSE
;
in_where
=
TRUE
;
...
...
@@ -356,7 +357,6 @@ parse_statement(StatementClass *stmt)
if
(
in_select
)
{
if
(
in_distinct
)
{
mylog
(
"in distinct
\n
"
);
...
...
@@ -378,7 +378,8 @@ parse_statement(StatementClass *stmt)
}
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
);
if
(
quote
||
dquote
)
continue
;
...
...
@@ -389,7 +390,6 @@ parse_statement(StatementClass *stmt)
in_expr
=
FALSE
;
in_field
=
FALSE
;
}
else
if
(
token
[
0
]
==
'('
)
{
blevel
++
;
...
...
@@ -414,7 +414,6 @@ parse_statement(StatementClass *stmt)
if
(
!
in_field
)
{
if
(
!
token
[
0
])
continue
;
...
...
@@ -462,7 +461,6 @@ parse_statement(StatementClass *stmt)
blevel
=
1
;
continue
;
}
else
{
strcpy
(
fi
[
stmt
->
nfld
]
->
name
,
token
);
...
...
@@ -478,9 +476,9 @@ parse_statement(StatementClass *stmt)
continue
;
}
/*
*************************/
/* We are in a field now */
/*************************
*/
/*
* We are in a field now
*/
if
(
in_dot
)
{
stmt
->
nfld
--
;
...
...
@@ -494,7 +492,6 @@ parse_statement(StatementClass *stmt)
mylog
(
"in_dot: got comma
\n
"
);
in_field
=
FALSE
;
}
continue
;
}
...
...
@@ -547,12 +544,10 @@ parse_statement(StatementClass *stmt)
fi
[
stmt
->
nfld
-
1
]
->
expr
=
TRUE
;
fi
[
stmt
->
nfld
-
1
]
->
name
[
0
]
=
'\0'
;
mylog
(
"*** setting expression
\n
"
);
}
if
(
in_from
)
{
if
(
!
in_table
)
{
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
;
/* Resolve field names with tables */
for
(
i
=
0
;
i
<
stmt
->
nfld
;
i
++
)
{
if
(
fi
[
i
]
->
func
||
fi
[
i
]
->
expr
||
fi
[
i
]
->
numeric
)
{
fi
[
i
]
->
ti
=
NULL
;
...
...
@@ -621,7 +614,6 @@ parse_statement(StatementClass *stmt)
parse
=
FALSE
;
continue
;
}
else
if
(
fi
[
i
]
->
quote
)
{
/* handle as text */
fi
[
i
]
->
ti
=
NULL
;
...
...
@@ -629,7 +621,6 @@ parse_statement(StatementClass *stmt)
fi
[
i
]
->
precision
=
0
;
continue
;
}
/* it's a dot, resolve to table or alias */
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
);
/******************************************************/
/* 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 */
for
(
i
=
0
;
i
<
stmt
->
ntab
;
i
++
)
{
/* See if already got it */
char
found
=
FALSE
;
...
...
@@ -689,7 +678,6 @@ parse_statement(StatementClass *stmt)
if
(
!
found
)
{
mylog
(
"PARSE: Getting SQLColumns for table[%d]='%s'
\n
"
,
i
,
ti
[
i
]
->
name
);
result
=
SQLAllocStmt
(
stmt
->
hdbc
,
&
hcol_stmt
);
...
...
@@ -713,7 +701,6 @@ parse_statement(StatementClass *stmt)
mylog
(
" Success
\n
"
);
if
(
!
(
conn
->
ntables
%
COL_INCR
))
{
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
*
));
...
...
@@ -762,18 +749,13 @@ parse_statement(StatementClass *stmt)
mylog
(
"associate col_info: i=%d, k=%d
\n
"
,
i
,
k
);
}
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
;)
{
/* Dont worry about functions or quotes */
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 */
else
if
(
fi
[
i
]
->
name
[
0
]
==
'*'
)
{
char
do_all_tables
;
int
total_cols
,
old_alloc
,
...
...
@@ -810,7 +791,6 @@ parse_statement(StatementClass *stmt)
increased_cols
=
total_cols
-
1
;
/* Allocate some more field pointers if necessary */
/*------------------------------------------------------------- */
old_alloc
=
((
stmt
->
nfld
-
1
)
/
FLD_INCR
+
1
)
*
FLD_INCR
;
new_size
=
stmt
->
nfld
+
increased_cols
;
...
...
@@ -830,8 +810,6 @@ parse_statement(StatementClass *stmt)
stmt
->
fi
=
fi
;
}
/*------------------------------------------------------------- */
/*
* copy any other fields (if there are any) up past the
* expansion
...
...
@@ -843,21 +821,16 @@ parse_statement(StatementClass *stmt)
}
mylog
(
"done copying fields
\n
"
);
/*------------------------------------------------------------- */
/* Set the new number of fields */
stmt
->
nfld
+=
increased_cols
;
mylog
(
"stmt->nfld now at %d
\n
"
,
stmt
->
nfld
);
/*------------------------------------------------------------- */
/* copy the new field info */
do_all_tables
=
(
fi
[
i
]
->
ti
?
FALSE
:
TRUE
);
for
(
k
=
0
;
k
<
(
do_all_tables
?
stmt
->
ntab
:
1
);
k
++
)
{
TABLE_INFO
*
the_ti
=
do_all_tables
?
ti
[
k
]
:
fi
[
i
]
->
ti
;
cols
=
QR_get_num_tuples
(
the_ti
->
col_info
->
result
);
...
...
@@ -890,8 +863,6 @@ parse_statement(StatementClass *stmt)
i
+=
cols
;
mylog
(
"i now at %d
\n
"
,
i
);
}
/*------------------------------------------------------------- */
}
/*
...
...
@@ -901,7 +872,6 @@ parse_statement(StatementClass *stmt)
*/
else
if
(
fi
[
i
]
->
ti
)
{
if
(
!
searchColInfo
(
fi
[
i
]
->
ti
->
col_info
,
fi
[
i
]))
parse
=
FALSE
;
...
...
@@ -925,13 +895,11 @@ parse_statement(StatementClass *stmt)
}
}
if
(
!
parse
)
stmt
->
parse_status
=
STMT_PARSE_INCOMPLETE
;
else
stmt
->
parse_status
=
STMT_PARSE_COMPLETE
;
mylog
(
"done parse_statement: parse=%d, parse_status=%d
\n
"
,
parse
,
stmt
->
parse_status
);
return
parse
;
}
src/interfaces/odbc/pgtypes.c
View file @
296e7ba2
/* Module: pgtypes.c
/*--------
* Module: pgtypes.c
*
* Description: This module contains routines for getting information
* about the supported Postgres data types. Only the function
* pgtype_to_sqltype() returns an unknown condition. All other
* functions return a suitable default so that even data types that
* are not directly supported can be used (it is handled as char data).
* about the supported Postgres data types. Only the
* function pgtype_to_sqltype() returns an unknown condition.
* All other functions return a suitable default so that
* even data types that are not directly supported can be
* used (it is handled as char data).
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#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
);
/*
* these are the types we support. all of the pgtype_ functions should
* return values for each one of these.
* Even types not directly supported are handled as character types
* so all types should work (points, etc.)
*/
/*
these are the types we support. all of the pgtype_ functions should */
/* return values for each one of these. */
/* Even types not directly supported are handled as character types
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[] = {
PG_TYPE_CHAR,
...
...
@@ -102,6 +107,7 @@ Int2 sqlTypes[] = {
0
};
Int4
sqltype_to_pgtype
(
SWORD
fSqlType
)
{
...
...
@@ -109,7 +115,6 @@ sqltype_to_pgtype(SWORD fSqlType)
switch
(
fSqlType
)
{
case
SQL_BINARY
:
pgType
=
PG_TYPE_BYTEA
;
break
;
...
...
@@ -185,15 +190,19 @@ sqltype_to_pgtype(SWORD fSqlType)
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
know. This allows for supporting
types that are unknown. All other pg routines in here return a suitable default.
*/
/*
* 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
* know. This allows for supporting
* types that are unknown. All other pg routines in here return a suitable default.
*/
Int2
pgtype_to_sqltype
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -228,7 +237,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case
PG_TYPE_INT4
:
return
SQL_INTEGER
;
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case
PG_TYPE_INT8
:
return
SQL_CHAR
;
...
...
@@ -253,20 +262,20 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
return
globals
.
bools_as_char
?
SQL_CHAR
:
SQL_BIT
;
default:
/*
* 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
* list, just return.
*/
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
/* hack until permanent
* type is available */
/* hack until permanent type is available */
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
return
SQL_LONGVARBINARY
;
return
globals
.
unknowns_as_longvarchar
?
SQL_LONGVARCHAR
:
SQL_VARCHAR
;
}
}
Int2
pgtype_to_ctype
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -305,21 +314,21 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
return
SQL_C_BINARY
;
default:
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
/* hack until permanent
* type is available */
/* hack until permanent type is available */
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
return
SQL_C_BINARY
;
return
SQL_C_CHAR
;
}
}
char
*
pgtype_to_name
(
StatementClass
*
stmt
,
Int4
type
)
{
switch
(
type
)
{
case
PG_TYPE_CHAR
:
return
"char"
;
case
PG_TYPE_CHAR
:
return
"char"
;
case
PG_TYPE_CHAR2
:
return
"char2"
;
case
PG_TYPE_CHAR4
:
...
...
@@ -369,8 +378,8 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
return
PG_TYPE_LO_NAME
;
default:
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
/* hack until permanent
* type is available */
/* hack until permanent type is available */
if
(
type
==
stmt
->
hdbc
->
lobj_type
)
return
PG_TYPE_LO_NAME
;
/*
...
...
@@ -381,6 +390,7 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
}
}
static
Int2
getNumericScale
(
StatementClass
*
stmt
,
Int4
type
,
int
col
)
{
...
...
@@ -417,6 +427,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
PG_NUMERIC_MAX_SCALE
);
}
static
Int4
getNumericPrecision
(
StatementClass
*
stmt
,
Int4
type
,
int
col
)
{
...
...
@@ -453,6 +464,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
PG_NUMERIC_MAX_PRECISION
);
}
Int4
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
;
}
/* 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
pgtype_precision
(
StatementClass
*
stmt
,
Int4
type
,
int
col
,
int
handle_unknown_size_as
)
{
switch
(
type
)
{
case
PG_TYPE_CHAR
:
return
1
;
case
PG_TYPE_CHAR2
:
...
...
@@ -597,10 +609,10 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
}
}
Int4
pgtype_display_size
(
StatementClass
*
stmt
,
Int4
type
,
int
col
,
int
handle_unknown_size_as
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
...
...
@@ -628,22 +640,22 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
case
PG_TYPE_FLOAT8
:
return
22
;
/* Character types use regular precision */
/* Character types use regular precision */
default:
return
pgtype_precision
(
stmt
,
type
,
col
,
handle_unknown_size_as
);
}
}
/* 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
pgtype_length
(
StatementClass
*
stmt
,
Int4
type
,
int
col
,
int
handle_unknown_size_as
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
return
2
;
...
...
@@ -674,19 +686,18 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
case
PG_TYPE_TIMESTAMP
:
return
16
;
/* Character types (and NUMERIC) use the default precision */
/* Character types (and NUMERIC) use the default precision */
default:
return
pgtype_precision
(
stmt
,
type
,
col
,
handle_unknown_size_as
);
}
}
Int2
pgtype_scale
(
StatementClass
*
stmt
,
Int4
type
,
int
col
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
case
PG_TYPE_OID
:
case
PG_TYPE_XID
:
...
...
@@ -697,10 +708,10 @@ pgtype_scale(StatementClass *stmt, Int4 type, int col)
case
PG_TYPE_MONEY
:
case
PG_TYPE_BOOL
:
/*
* Number of digits to the right of the decimal point in
* "yyyy-mm=dd hh:mm:ss[.f...]"
*/
/*
* Number of digits to the right of the decimal point in
* "yyyy-mm=dd hh:mm:ss[.f...]"
*/
case
PG_TYPE_ABSTIME
:
case
PG_TYPE_DATETIME
:
case
PG_TYPE_TIMESTAMP
:
...
...
@@ -729,24 +740,24 @@ pgtype_radix(StatementClass *stmt, Int4 type)
case
PG_TYPE_MONEY
:
case
PG_TYPE_FLOAT8
:
return
10
;
default:
return
-
1
;
}
}
Int2
pgtype_nullable
(
StatementClass
*
stmt
,
Int4
type
)
{
return
SQL_NULLABLE
;
/* everything should be nullable */
}
Int2
pgtype_auto_increment
(
StatementClass
*
stmt
,
Int4
type
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
case
PG_TYPE_OID
:
case
PG_TYPE_XID
:
...
...
@@ -770,6 +781,7 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_case_sensitive
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -792,6 +804,7 @@ pgtype_case_sensitive(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_money
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -804,6 +817,7 @@ pgtype_money(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_searchable
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -825,6 +839,7 @@ pgtype_searchable(StatementClass *stmt, Int4 type)
}
}
Int2
pgtype_unsigned
(
StatementClass
*
stmt
,
Int4
type
)
{
...
...
@@ -848,12 +863,12 @@ pgtype_unsigned(StatementClass *stmt, Int4 type)
}
}
char
*
pgtype_literal_prefix
(
StatementClass
*
stmt
,
Int4
type
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
case
PG_TYPE_OID
:
case
PG_TYPE_XID
:
...
...
@@ -869,12 +884,12 @@ pgtype_literal_prefix(StatementClass *stmt, Int4 type)
}
}
char
*
pgtype_literal_suffix
(
StatementClass
*
stmt
,
Int4
type
)
{
switch
(
type
)
{
case
PG_TYPE_INT2
:
case
PG_TYPE_OID
:
case
PG_TYPE_XID
:
...
...
@@ -890,13 +905,14 @@ pgtype_literal_suffix(StatementClass *stmt, Int4 type)
}
}
char
*
pgtype_create_params
(
StatementClass
*
stmt
,
Int4
type
)
{
switch
(
type
)
{
case
PG_TYPE_CHAR
:
case
PG_TYPE_VARCHAR
:
return
"max. length"
;
case
PG_TYPE_CHAR
:
case
PG_TYPE_VARCHAR
:
return
"max. length"
;
default:
return
NULL
;
}
...
...
@@ -906,8 +922,10 @@ pgtype_create_params(StatementClass *stmt, Int4 type)
Int2
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
)
{
case
SQL_CHAR
:
...
...
@@ -951,7 +969,8 @@ sqltype_to_default_ctype(Int2 sqltype)
case
SQL_TIMESTAMP
:
return
SQL_C_TIMESTAMP
;
default:
/* should never happen */
default:
/* should never happen */
return
SQL_C_CHAR
;
}
}
...
...
src/interfaces/odbc/psqlodbc.c
View file @
296e7ba2
/* Module: psqlodbc.c
/*--------
* Module: psqlodbc.c
*
* Description: This module contains the main entry point (DllMain)
for the library.
*
It also contains functions to get and set global variables for the
* driver in the registry.
* Description: This module contains the main entry point (DllMain)
*
for the library. It also contains functions to get
*
and set global variables for the
driver in the registry.
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -59,7 +60,6 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
if
(
LOBYTE
(
wsaData
.
wVersion
)
!=
1
||
HIBYTE
(
wsaData
.
wVersion
)
!=
1
)
{
WSACleanup
();
return
FALSE
;
}
...
...
@@ -71,9 +71,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
break
;
case
DLL_PROCESS_DETACH
:
WSACleanup
();
return
TRUE
;
case
DLL_THREAD_DETACH
:
...
...
@@ -111,7 +109,8 @@ init(void)
#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.
*/
BOOL
...
...
@@ -131,12 +130,14 @@ _fini(void)
#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
Driver Manager do this. Also, the ordinal values of the
functions must match the value of fFunction in SQLGetFunctions()
*/
/*
* 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
* Driver Manager do this. Also, the ordinal values of the
* functions must match the value of fFunction in SQLGetFunctions()
*/
RETCODE
SQL_API
SQLDummyOrdinal
(
void
)
{
...
...
src/interfaces/odbc/qresult.c
View file @
296e7ba2
/* Module: qresult.c
/*---------
* Module: qresult.c
*
* Description: This module contains functions related to
* managing result information (i.e, fetching rows from the backend,
* managing the tuple cache, etc.) and retrieving it.
* Depending on the situation, a QResultClass will hold either data
* from the backend or a manually built result (see "qresult.h" to
* see which functions/macros are for manual or backend results.
* For manually built results, the QResultClass simply points to
* TupleList and ColumnInfo structures, which actually hold the data.
* managing result information (i.e, fetching rows
* from the backend, managing the tuple cache, etc.)
* and retrieving it. Depending on the situation, a
* QResultClass will hold either data from the backend
* or a manually built result (see "qresult.h" to
* see which functions/macros are for manual or backend
* results. For manually built results, the
* QResultClass simply points to TupleList and
* ColumnInfo structures, which actually hold the data.
*
* Classes: QResultClass (Functions prefix: "QR_")
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
---------
*/
#include "qresult.h"
...
...
@@ -31,8 +34,11 @@
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
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
"
);
}
void
QR_set_position
(
QResultClass
*
self
,
int
pos
)
{
self
->
tupleField
=
self
->
backend_tuples
+
((
self
->
base
+
pos
)
*
self
->
num_fields
);
}
void
QR_set_cache_size
(
QResultClass
*
self
,
int
cache_size
)
{
self
->
cache_size
=
cache_size
;
}
void
QR_set_rowset_size
(
QResultClass
*
self
,
int
rowset_size
)
{
self
->
rowset_size
=
rowset_size
;
}
void
QR_inc_base
(
QResultClass
*
self
,
int
base_inc
)
{
self
->
base
+=
base_inc
;
}
/************************************/
/* CLASS QResult */
/************************************/
/*
* CLASS QResult
*/
QResultClass
*
QR_Constructor
(
void
)
{
...
...
@@ -111,13 +121,13 @@ QR_Constructor(void)
rv
->
cache_size
=
globals
.
fetch_max
;
rv
->
rowset_size
=
1
;
}
mylog
(
"exit QR_Constructor
\n
"
);
return
rv
;
}
void
QR_Destructor
(
QResultClass
*
self
)
{
...
...
@@ -127,8 +137,10 @@ QR_Destructor(QResultClass *self)
if
(
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
))
QR_close
(
self
);
/* close the cursor if there is one */
...
...
@@ -153,9 +165,9 @@ QR_Destructor(QResultClass *self)
free
(
self
);
mylog
(
"QResult: exit DESTRUCTOR
\n
"
);
}
void
QR_set_command
(
QResultClass
*
self
,
char
*
msg
)
{
...
...
@@ -165,6 +177,7 @@ QR_set_command(QResultClass *self, char *msg)
self
->
command
=
msg
?
strdup
(
msg
)
:
NULL
;
}
void
QR_set_notice
(
QResultClass
*
self
,
char
*
msg
)
{
...
...
@@ -174,6 +187,7 @@ QR_set_notice(QResultClass *self, char *msg)
self
->
notice
=
msg
?
strdup
(
msg
)
:
NULL
;
}
void
QR_free_memory
(
QResultClass
*
self
)
{
...
...
@@ -187,7 +201,6 @@ QR_free_memory(QResultClass *self)
if
(
self
->
backend_tuples
)
{
for
(
row
=
0
;
row
<
fcount
;
row
++
)
{
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
"
);
}
/* This function is called by send_query() */
char
QR_fetch_tuples
(
QResultClass
*
self
,
ConnectionClass
*
conn
,
char
*
cursor
)
{
int
tuple_size
;
/* If called from send_query the first time (conn != NULL), */
/* then set the inTuples state, */
/* and read the tuples. If conn is NULL, */
/* it implies that we are being called from next_tuple(), */
/* like to get more rows so don't call next_tuple again! */
/*
* If called from send_query the first time (conn != NULL),
* then set the inTuples state,
* and read the tuples. If conn is NULL,
* 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
)
{
self
->
conn
=
conn
;
...
...
@@ -242,8 +258,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *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
))
{
self
->
status
=
PGRES_FIELDS_OK
;
...
...
@@ -275,7 +294,6 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
self
->
inTuples
=
TRUE
;
/* Force a read to occur in next_tuple */
self
->
fcount
=
tuple_size
+
1
;
self
->
fetch_count
=
tuple_size
+
1
;
...
...
@@ -285,9 +303,10 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
}
else
{
/* Always have to read the field attributes. */
/* But we dont have to reallocate memory for them! */
/*
* Always have to read the field attributes.
* But we dont have to reallocate memory for them!
*/
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
QR_close
(
QResultClass
*
self
)
{
...
...
@@ -346,12 +368,12 @@ QR_close(QResultClass *self)
}
QR_Destructor
(
res
);
}
}
return
TRUE
;
}
/* This function is called by fetch_tuples() AND SQLFetch() */
int
QR_next_tuple
(
QResultClass
*
self
)
...
...
@@ -360,7 +382,7 @@ QR_next_tuple(QResultClass *self)
QResultClass
*
res
;
SocketClass
*
sock
;
/* Speed up access */
/* Speed up access */
int
fetch_count
=
self
->
fetch_count
;
int
fcount
=
self
->
fcount
;
int
fetch_size
,
...
...
@@ -370,30 +392,31 @@ QR_next_tuple(QResultClass *self)
TupleField
*
the_tuples
=
self
->
backend_tuples
;
/* ERROR_MSG_LENGTH is sufficient */
static
char
msgbuffer
[
ERROR_MSG_LENGTH
+
1
];
char
cmdbuffer
[
ERROR_MSG_LENGTH
+
1
];
/* QR_set_command() dups
* this string so dont
* need static */
/* QR_set_command() dups this string so doesn't need static */
char
cmdbuffer
[
ERROR_MSG_LENGTH
+
1
];
char
fetch
[
128
];
QueryInfo
qi
;
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
);
self
->
tupleField
=
the_tuples
+
(
fetch_count
*
self
->
num_fields
);
/* next row */
self
->
fetch_count
++
;
return
TRUE
;
}
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 */
mylog
(
"next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d
\n
"
,
fcount
,
fetch_count
);
self
->
tupleField
=
NULL
;
self
->
status
=
PGRES_END_TUPLES
;
return
-
1
;
/* end of tuples */
/* end of tuples */
return
-
1
;
}
else
{
/*
* 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,
...
...
@@ -403,7 +426,6 @@ QR_next_tuple(QResultClass *self)
if
(
!
self
->
inTuples
)
{
if
(
!
globals
.
use_declarefetch
)
{
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
)
{
/* not a correction */
{
/* not a correction */
/* Determine the optimum cache size. */
if
(
globals
.
fetch_max
%
self
->
rowset_size
==
0
)
fetch_size
=
globals
.
fetch_max
;
...
...
@@ -427,8 +449,8 @@ QR_next_tuple(QResultClass *self)
self
->
fetch_count
=
1
;
}
else
{
/* need to correct */
{
/* need to correct */
corrected
=
TRUE
;
fetch_size
=
end_tuple
-
fcount
;
...
...
@@ -437,10 +459,8 @@ QR_next_tuple(QResultClass *self)
offset
=
self
->
fetch_count
;
self
->
fetch_count
++
;
}
self
->
backend_tuples
=
(
TupleField
*
)
realloc
(
self
->
backend_tuples
,
self
->
num_fields
*
sizeof
(
TupleField
)
*
self
->
cache_size
);
if
(
!
self
->
backend_tuples
)
{
...
...
@@ -484,17 +504,16 @@ QR_next_tuple(QResultClass *self)
self
->
fcount
=
0
;
}
sock
=
CC_get_socket
(
self
->
conn
);
self
->
tupleField
=
NULL
;
for
(;;)
{
id
=
SOCK_get_char
(
sock
);
switch
(
id
)
{
case
'T'
:
/* Tuples within tuples cannot be handled */
self
->
status
=
PGRES_BAD_RESPONSE
;
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"
);
return
FALSE
;
}
self
->
fcount
++
;
break
;
/* continue reading */
case
'C'
:
/* End of tuple list */
SOCK_get_string
(
sock
,
cmdbuffer
,
ERROR_MSG_LENGTH
);
QR_set_command
(
self
,
cmdbuffer
);
...
...
@@ -537,7 +554,6 @@ QR_next_tuple(QResultClass *self)
self
->
inTuples
=
FALSE
;
if
(
self
->
fcount
>
0
)
{
qlog
(
" [ fetched %d rows ]
\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
;
}
else
{
/* We are surely done here (we read 0
*
tuples) */
{
/* We are surely done here (we read 0
tuples) */
qlog
(
" [ fetched 0 rows ]
\n
"
);
mylog
(
"_next_tuple: 'C': DONE (fcount == 0)
\n
"
);
return
-
1
;
/* end of tuples */
...
...
@@ -585,6 +601,7 @@ QR_next_tuple(QResultClass *self)
return
TRUE
;
}
char
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
);
ColumnInfoClass
*
flds
;
/* set the current row to read the fields into */
this_tuplefield
=
self
->
backend_tuples
+
(
self
->
fcount
*
num_fields
);
...
...
@@ -630,7 +646,6 @@ QR_read_tuple(QResultClass *self, char binary)
}
else
{
/*
* NO, the field is not null. so get at first the length of
* the field (four bytes)
...
...
src/interfaces/odbc/results.c
View file @
296e7ba2
/* Module: results.c
/*-------
* Module: results.c
*
* Description: This module contains functions related to
* retrieving result information through the ODBC API.
*
* Classes: n/a
*
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
SQLColAttributes,
* SQLGetData, SQLFetch, SQLExtendedFetch,
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
* SQL
ColAttributes, SQL
GetData, SQLFetch, SQLExtendedFetch,
* SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
* SQLSetCursorName, SQLGetCursorName
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -42,7 +43,6 @@
extern
GLOBAL_VALUES
globals
;
RETCODE
SQL_API
SQLRowCount
(
HSTMT
hstmt
,
...
...
@@ -81,7 +81,6 @@ SQLRowCount(
}
else
{
res
=
SC_get_Result
(
stmt
);
if
(
res
&&
pcrow
)
{
...
...
@@ -97,7 +96,6 @@ SQLRowCount(
else
{
*
pcrow
=
-
1
;
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
SQLNumResultCols
(
HSTMT
hstmt
,
...
...
@@ -135,7 +133,6 @@ SQLNumResultCols(
parse_ok
=
FALSE
;
if
(
globals
.
parse
&&
stmt
->
statement_type
==
STMT_TYPE_SELECT
)
{
if
(
stmt
->
parse_status
==
STMT_PARSE_NONE
)
{
mylog
(
"SQLNumResultCols: calling parse_statement on stmt=%u
\n
"
,
stmt
);
...
...
@@ -152,7 +149,6 @@ SQLNumResultCols(
if
(
!
parse_ok
)
{
SC_pre_execute
(
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
SQLDescribeCol
(
HSTMT
hstmt
,
...
...
@@ -205,7 +199,6 @@ SQLDescribeCol(
int
len
=
0
;
RETCODE
result
;
mylog
(
"%s: entering...
\n
"
,
func
);
if
(
!
stmt
)
...
...
@@ -219,29 +212,25 @@ SQLDescribeCol(
SC_clear_error
(
stmt
);
/*
*
Dont check for bookmark column. This is the responsibility of the
*
driver manager.
*
Dont check for bookmark column. This is the responsibility of the
*
driver manager.
*/
icol
--
;
/* use zero based column numbers */
parse_ok
=
FALSE
;
if
(
globals
.
parse
&&
stmt
->
statement_type
==
STMT_TYPE_SELECT
)
{
if
(
stmt
->
parse_status
==
STMT_PARSE_NONE
)
{
mylog
(
"SQLDescribeCol: calling parse_statement on stmt=%u
\n
"
,
stmt
);
parse_statement
(
stmt
);
}
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
(
icol
>=
stmt
->
nfld
)
{
stmt
->
errornumber
=
STMT_INVALID_COLUMN_NUMBER_ERROR
;
...
...
@@ -261,11 +250,10 @@ SQLDescribeCol(
}
}
/*
*
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
*
old fashioned way.
*
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
*
old fashioned way.
*/
if
(
!
parse_ok
)
{
...
...
@@ -295,20 +283,19 @@ SQLDescribeCol(
col_name
=
QR_get_fieldname
(
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 fieldtype = %d
\n
"
,
icol
,
fieldtype
);
mylog
(
"describeCol: col %d precision = %d
\n
"
,
icol
,
precision
);
result
=
SQL_SUCCESS
;
/*
***********************/
/* COLUMN NAME */
/***********************
*/
/*
* COLUMN NAME
*/
len
=
strlen
(
col_name
);
if
(
pcbColName
)
...
...
@@ -326,10 +313,9 @@ SQLDescribeCol(
}
}
/************************/
/* SQL TYPE */
/************************/
/*
* SQL TYPE
*/
if
(
pfSqlType
)
{
*
pfSqlType
=
pgtype_to_sqltype
(
stmt
,
fieldtype
);
...
...
@@ -337,12 +323,11 @@ SQLDescribeCol(
mylog
(
"describeCol: col %d *pfSqlType = %d
\n
"
,
icol
,
*
pfSqlType
);
}
/*
***********************/
/* PRECISION */
/***********************
*/
/*
* PRECISION
*/
if
(
pcbColDef
)
{
if
(
precision
<
0
)
precision
=
0
;
/* "I dont know" */
...
...
@@ -351,9 +336,9 @@ SQLDescribeCol(
mylog
(
"describeCol: col %d *pcbColDef = %d
\n
"
,
icol
,
*
pcbColDef
);
}
/*
***********************/
/* SCALE */
/***********************
*/
/*
* SCALE
*/
if
(
pibScale
)
{
Int2
scale
;
...
...
@@ -366,9 +351,9 @@ SQLDescribeCol(
mylog
(
"describeCol: col %d *pibScale = %d
\n
"
,
icol
,
*
pibScale
);
}
/*
***********************/
/* NULLABILITY */
/***********************
*/
/*
* NULLABILITY
*/
if
(
pfNullable
)
{
*
pfNullable
=
(
parse_ok
)
?
stmt
->
fi
[
icol
]
->
nullable
:
pgtype_nullable
(
stmt
,
fieldtype
);
...
...
@@ -379,8 +364,8 @@ SQLDescribeCol(
return
result
;
}
/* Returns result column descriptor information for a result set. */
/* Returns result column descriptor information for a result set. */
RETCODE
SQL_API
SQLColAttributes
(
HSTMT
hstmt
,
...
...
@@ -421,16 +406,16 @@ SQLColAttributes(
icol
--
;
unknown_sizes
=
globals
.
unknown_sizes
;
/* atoi(ci->unknown_sizes);
* */
if
(
unknown_sizes
==
UNKNOWNS_AS_DONTKNOW
)
/* not appropriate for
* SQLColAttributes() */
/* atoi(ci->unknown_sizes); */
unknown_sizes
=
globals
.
unknown_sizes
;
/* not appropriate for SQLColAttributes() */
if
(
unknown_sizes
==
UNKNOWNS_AS_DONTKNOW
)
unknown_sizes
=
UNKNOWNS_AS_MAX
;
parse_ok
=
FALSE
;
if
(
globals
.
parse
&&
stmt
->
statement_type
==
STMT_TYPE_SELECT
)
{
if
(
stmt
->
parse_status
==
STMT_PARSE_NONE
)
{
mylog
(
"SQLColAttributes: calling parse_statement
\n
"
);
...
...
@@ -453,7 +438,6 @@ SQLColAttributes(
if
(
stmt
->
parse_status
!=
STMT_PARSE_FATAL
&&
stmt
->
fi
&&
stmt
->
fi
[
icol
])
{
if
(
icol
>=
cols
)
{
stmt
->
errornumber
=
STMT_INVALID_COLUMN_NUMBER_ERROR
;
...
...
@@ -461,7 +445,6 @@ SQLColAttributes(
SC_log_error
(
func
,
""
,
stmt
);
return
SQL_ERROR
;
}
field_type
=
stmt
->
fi
[
icol
]
->
type
;
if
(
field_type
>
0
)
parse_ok
=
TRUE
;
...
...
@@ -522,12 +505,11 @@ SQLColAttributes(
value
=
pgtype_case_sensitive
(
stmt
,
field_type
);
break
;
/*
* This special case is handled above.
*
* case SQL_COLUMN_COUNT:
*/
/*
* This special case is handled above.
*
* case SQL_COLUMN_COUNT:
*/
case
SQL_COLUMN_DISPLAY_SIZE
:
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
);
break
;
}
/* otherwise same as column name -- FALL
*
THROUGH!!! */
}
/* otherwise same as column name -- FALL
THROUGH!!! */
case
SQL_COLUMN_NAME
:
p
=
(
parse_ok
)
?
stmt
->
fi
[
icol
]
->
name
:
QR_get_fieldname
(
stmt
->
result
,
icol
);
mylog
(
"SQLColAttr: COLUMN_NAME = '%s'
\n
"
,
p
);
...
...
@@ -590,7 +571,6 @@ SQLColAttributes(
break
;
case
SQL_COLUMN_TABLE_NAME
:
p
=
(
parse_ok
&&
stmt
->
fi
[
icol
]
->
ti
)
?
stmt
->
fi
[
icol
]
->
ti
->
name
:
""
;
mylog
(
"SQLColAttr: TABLE_NAME = '%s'
\n
"
,
p
);
...
...
@@ -612,14 +592,12 @@ SQLColAttributes(
break
;
case
SQL_COLUMN_UPDATABLE
:
/*
* Neither Access or Borland care about this.
*
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
* else
*/
value
=
SQL_ATTR_WRITE
;
mylog
(
"SQLColAttr: UPDATEABLE = %d
\n
"
,
value
);
...
...
@@ -648,19 +626,17 @@ SQLColAttributes(
*
pcbDesc
=
len
;
}
else
{
/* numeric data */
{
/* numeric data */
if
(
pfDesc
)
*
pfDesc
=
value
;
}
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
SQLGetData
(
HSTMT
hstmt
,
...
...
@@ -707,7 +683,6 @@ SQLGetData(
if
(
icol
==
0
)
{
if
(
stmt
->
options
.
use_bookmarks
==
SQL_UB_OFF
)
{
stmt
->
errornumber
=
STMT_COLNUM_ERROR
;
...
...
@@ -726,12 +701,9 @@ SQLGetData(
}
get_bookmark
=
TRUE
;
}
else
{
/* use zero-based column numbers */
icol
--
;
...
...
@@ -770,7 +742,8 @@ SQLGetData(
}
}
else
{
/* it's a SOCKET result (backend data) */
{
/* it's a SOCKET result (backend data) */
if
(
stmt
->
currTuple
==
-
1
||
!
res
||
!
res
->
tupleField
)
{
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"), */
/* advances the cursor. */
/*
* Returns data for bound columns in the current row ("hstmt->iCursor"),
* advances the cursor.
*/
RETCODE
SQL_API
SQLFetch
(
HSTMT
hstmt
)
...
...
@@ -892,7 +865,6 @@ SQLFetch(
return
SQL_ERROR
;
}
if
(
stmt
->
status
!=
STMT_FINISHED
)
{
stmt
->
errornumber
=
STMT_STATUS_ERROR
;
...
...
@@ -917,8 +889,8 @@ SQLFetch(
return
SC_fetch
(
stmt
);
}
/* This fetchs a block of data (rowset). */
/* This fetchs a block of data (rowset). */
RETCODE
SQL_API
SQLExtendedFetch
(
HSTMT
hstmt
,
...
...
@@ -1020,7 +992,6 @@ SQLExtendedFetch(
switch
(
fFetchType
)
{
case
SQL_FETCH_NEXT
:
/*
* From the odbc spec... If positioned before the start of the
* RESULT SET, then this should be equivalent to
...
...
@@ -1031,36 +1002,25 @@ SQLExtendedFetch(
stmt
->
rowset_start
=
0
;
else
{
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
);
break
;
case
SQL_FETCH_PRIOR
:
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
* RESULT SET, then this should be equivalent to
* SQL_FETCH_LAST.
*/
if
(
stmt
->
rowset_start
>=
num_tuples
)
{
stmt
->
rowset_start
=
num_tuples
<=
0
?
0
:
(
num_tuples
-
stmt
->
options
.
rowset_size
);
}
else
{
stmt
->
rowset_start
-=
stmt
->
options
.
rowset_size
;
}
break
;
case
SQL_FETCH_FIRST
:
...
...
@@ -1091,11 +1051,9 @@ SQLExtendedFetch(
/* Position with respect to the end of the result set */
else
stmt
->
rowset_start
=
num_tuples
+
irow
;
break
;
case
SQL_FETCH_RELATIVE
:
/*
* Refresh the current rowset -- not currently implemented,
* but lie anyway
...
...
@@ -1104,25 +1062,20 @@ SQLExtendedFetch(
break
;
stmt
->
rowset_start
+=
irow
;
break
;
case
SQL_FETCH_BOOKMARK
:
stmt
->
rowset_start
=
irow
-
1
;
break
;
default:
SC_log_error
(
func
,
"Unsupported SQLExtendedFetch Direction"
,
stmt
);
return
SQL_ERROR
;
}
/***********************************/
/* CHECK FOR PROPER CURSOR STATE */
/***********************************/
/*
* CHECK FOR PROPER CURSOR STATE
*/
/*
* Handle Declare Fetch style specially because the end is not really
...
...
@@ -1172,7 +1125,6 @@ SQLExtendedFetch(
truncated
=
error
=
FALSE
;
for
(
i
=
0
;
i
<
stmt
->
options
.
rowset_size
;
i
++
)
{
stmt
->
bind_row
=
i
;
/* set the binding location */
result
=
SC_fetch
(
stmt
);
...
...
@@ -1212,21 +1164,21 @@ SQLExtendedFetch(
*
pcrow
=
i
;
if
(
i
==
0
)
return
SQL_NO_DATA_FOUND
;
/* Only DeclareFetch should wind
* up here */
/* Only DeclareFetch should wind up here */
return
SQL_NO_DATA_FOUND
;
else
if
(
error
)
return
SQL_ERROR
;
else
if
(
truncated
)
return
SQL_SUCCESS_WITH_INFO
;
else
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 */
RETCODE
SQL_API
SQLMoreResults
(
...
...
@@ -1235,8 +1187,11 @@ SQLMoreResults(
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
SQLSetPos
(
HSTMT
hstmt
,
...
...
@@ -1301,11 +1256,10 @@ SQLSetPos(
stmt
->
currTuple
=
stmt
->
rowset_start
+
irow
;
return
SQL_SUCCESS
;
}
/* Sets options that control the behavior of cursors. */
/* Sets options that control the behavior of cursors. */
RETCODE
SQL_API
SQLSetScrollOptions
(
HSTMT
hstmt
,
...
...
@@ -1320,8 +1274,7 @@ SQLSetScrollOptions(
}
/* Set the cursor name on a statement handle */
/* Set the cursor name on a statement handle */
RETCODE
SQL_API
SQLSetCursorName
(
HSTMT
hstmt
,
...
...
@@ -1354,8 +1307,8 @@ SQLSetCursorName(
return
SQL_SUCCESS
;
}
/* Return the cursor name for a statement handle */
/* Return the cursor name for a statement handle */
RETCODE
SQL_API
SQLGetCursorName
(
HSTMT
hstmt
,
...
...
src/interfaces/odbc/setup.c
View file @
296e7ba2
/* Module: setup.c
/*-------
* Module: setup.c
*
* Description: This module contains the setup functions for
* adding/modifying a Data Source in the ODBC.INI portion
...
...
@@ -9,7 +10,7 @@
* API functions: ConfigDSN
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#include "psqlodbc.h"
...
...
@@ -28,7 +29,7 @@
extern
HINSTANCE
NEAR
s_hModule
;
/* Saved module handle. */
extern
GLOBAL_VALUES
globals
;
/* Constants
---------------------------------------------------------------
*/
/* Constants */
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#ifdef WIN32
...
...
@@ -40,7 +41,7 @@ extern GLOBAL_VALUES globals;
#define MAXDSNAME (32+1)
/* Max data source name length */
/* Globals
-----------------------------------------------------------------
*/
/* Globals */
/* NOTE: All these are used by the dialog procedures */
typedef
struct
tagSETUPDLG
{
...
...
@@ -55,24 +56,26 @@ typedef struct tagSETUPDLG
/* Prototypes
--------------------------------------------------------------
*/
/* Prototypes */
void
INTFUNC
CenterDialog
(
HWND
hdlg
);
int
CALLBACK
ConfigDlgProc
(
HWND
hdlg
,
WORD
wMsg
,
WPARAM
wParam
,
LPARAM
lParam
);
void
INTFUNC
ParseAttributes
(
LPCSTR
lpszAttributes
,
LPSETUPDLG
lpsetupdlg
);
BOOL
INTFUNC
SetDSNAttributes
(
HWND
hwnd
,
LPSETUPDLG
lpsetupdlg
);
/* ConfigDSN ---------------------------------------------------------------
Description: ODBC Setup entry point
This entry point is called by the ODBC Installer
(see file header for more details)
Input : hwnd ----------- Parent window handle
fRequest ------- Request type (i.e., add, config, or remove)
lpszDriver ----- Driver name
lpszAttributes - data source attribute string
Output : TRUE success, FALSE otherwise
--------------------------------------------------------------------------*/
/*--------
* ConfigDSN
*
* Description: ODBC Setup entry point
* This entry point is called by the ODBC Installer
* (see file header for more details)
* Input : hwnd ----------- Parent window handle
* fRequest ------- Request type (i.e., add, config, or remove)
* lpszDriver ----- Driver name
* lpszAttributes - data source attribute string
* Output : TRUE success, FALSE otherwise
*--------
*/
BOOL
CALLBACK
ConfigDSN
(
HWND
hwnd
,
WORD
fRequest
,
...
...
@@ -111,7 +114,6 @@ ConfigDSN(HWND hwnd,
else
fSuccess
=
SQLRemoveDSNFromIni
(
lpsetupdlg
->
ci
.
dsn
);
}
/* Add or Configure data source */
else
{
...
...
@@ -134,7 +136,6 @@ ConfigDSN(HWND hwnd,
ConfigDlgProc
,
(
LONG
)
(
LPSTR
)
lpsetupdlg
));
}
else
if
(
lpsetupdlg
->
ci
.
dsn
[
0
])
fSuccess
=
SetDSNAttributes
(
hwnd
,
lpsetupdlg
);
else
...
...
@@ -148,11 +149,14 @@ ConfigDSN(HWND hwnd,
}
/* CenterDialog ------------------------------------------------------------
Description: Center the dialog over the frame window
Input : hdlg -- Dialog window handle
Output : None
--------------------------------------------------------------------------*/
/*-------
* CenterDialog
*
* Description: Center the dialog over the frame window
* Input : hdlg -- Dialog window handle
* Output : None
*-------
*/
void
INTFUNC
CenterDialog
(
HWND
hdlg
)
{
...
...
@@ -198,23 +202,22 @@ CenterDialog(HWND hdlg)
return
;
}
/*
ConfigDlgProc ----------------------------------------------------
-------
Description: Manage add data source name dialog
Input : hdlg --- Dialog window handle
wMsg --- Messag
e
wParam - Message parameter
l
Param - Message parameter
Output : TRUE if message processed, FALSE otherwise
--------------------------------------------------------------------------*/
/*-------
* ConfigDlgProc
* Description: Manage add data source name dialog
* Input : hdlg --- Dialog window handl
e
* wMsg --- Message
* w
Param - Message parameter
* lParam - Message parameter
* Output : TRUE if message processed, FALSE otherwise
*-------
*/
int
CALLBACK
ConfigDlgProc
(
HWND
hdlg
,
WORD
wMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
switch
(
wMsg
)
{
/* Initialize the dialog */
...
...
@@ -241,11 +244,9 @@ ConfigDlgProc(HWND hdlg,
/* Fill in any defaults */
getDSNdefaults
(
ci
);
/* Initialize dialog fields */
SetDlgStuff
(
hdlg
,
ci
);
if
(
lpsetupdlg
->
fDefault
)
{
EnableWindow
(
GetDlgItem
(
hdlg
,
IDC_DSNAME
),
FALSE
);
...
...
@@ -260,13 +261,10 @@ ConfigDlgProc(HWND hdlg,
return
TRUE
;
/* Focus was not set */
}
/* Process buttons */
/* Process buttons */
case
WM_COMMAND
:
switch
(
GET_WM_COMMAND_ID
(
wParam
,
lParam
))
{
/*
* Ensure the OK button is enabled only when a data
* source name
...
...
@@ -281,12 +279,11 @@ ConfigDlgProc(HWND hdlg,
EnableWindow
(
GetDlgItem
(
hdlg
,
IDOK
),
GetDlgItemText
(
hdlg
,
IDC_DSNAME
,
szItem
,
sizeof
(
szItem
)));
return
TRUE
;
}
break
;
/* Accept results */
/* Accept results */
case
IDOK
:
{
LPSETUPDLG
lpsetupdlg
;
...
...
@@ -297,8 +294,6 @@ ConfigDlgProc(HWND hdlg,
GetDlgItemText
(
hdlg
,
IDC_DSNAME
,
lpsetupdlg
->
ci
.
dsn
,
sizeof
(
lpsetupdlg
->
ci
.
dsn
));
/* Get Dialog Values */
GetDlgStuff
(
hdlg
,
&
lpsetupdlg
->
ci
);
...
...
@@ -306,13 +301,12 @@ ConfigDlgProc(HWND hdlg,
SetDSNAttributes
(
hdlg
,
lpsetupdlg
);
}
/* Return to caller */
/* Return to caller */
case
IDCANCEL
:
EndDialog
(
hdlg
,
wParam
);
return
TRUE
;
case
IDC_DRIVER
:
DialogBoxParam
(
s_hModule
,
MAKEINTRESOURCE
(
DLG_OPTIONS_DRV
),
hdlg
,
driver_optionsProc
,
(
LPARAM
)
NULL
);
...
...
@@ -330,7 +324,6 @@ ConfigDlgProc(HWND hdlg,
return
TRUE
;
}
}
break
;
}
...
...
@@ -339,11 +332,14 @@ ConfigDlgProc(HWND hdlg,
}
/* ParseAttributes ---------------------------------------------------------
Description: Parse attribute string moving values into the aAttr array
Input : lpszAttributes - Pointer to attribute string
Output : None (global aAttr normally updated)
--------------------------------------------------------------------------*/
/*-------
* ParseAttributes
*
* Description: Parse attribute string moving values into the aAttr array
* Input : lpszAttributes - Pointer to attribute string
* Output : None (global aAttr normally updated)
*-------
*/
void
INTFUNC
ParseAttributes
(
LPCSTR
lpszAttributes
,
LPSETUPDLG
lpsetupdlg
)
{
...
...
@@ -356,8 +352,8 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
memset
(
&
lpsetupdlg
->
ci
,
0
,
sizeof
(
ConnInfo
));
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
;
for
(;;
lpsz
++
)
{
...
...
@@ -370,15 +366,14 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
cbKey
=
lpsz
-
lpszStart
;
if
(
cbKey
<
sizeof
(
aszKey
))
{
_fmemcpy
(
aszKey
,
lpszStart
,
cbKey
);
aszKey
[
cbKey
]
=
'\0'
;
}
/* Locate end of key value */
lpszStart
=
++
lpsz
;
for
(;
*
lpsz
;
lpsz
++
)
;
for
(;
*
lpsz
;
lpsz
++
)
;
/* lpsetupdlg->aAttr[iElement].fSupplied = TRUE; */
_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
Input : hwnd - Parent window handle (plus globals)
Output : TRUE if successful, FALSE otherwise
--------------------------------------------------------------------------*/
/*--------
* SetDSNAttributes
*
* Description: Write data source attributes to ODBC.INI
* Input : hwnd - Parent window handle (plus globals)
* Output : TRUE if successful, FALSE otherwise
*--------
*/
BOOL
INTFUNC
SetDSNAttributes
(
HWND
hwndParent
,
LPSETUPDLG
lpsetupdlg
)
{
...
...
@@ -425,11 +422,9 @@ SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg)
return
FALSE
;
}
/* Update ODBC.INI */
writeDSNinfo
(
&
lpsetupdlg
->
ci
);
/* If the data source name has changed, remove the old name */
if
(
lstrcmpi
(
lpsetupdlg
->
szDSN
,
lpsetupdlg
->
ci
.
dsn
))
SQLRemoveDSNFromIni
(
lpsetupdlg
->
szDSN
);
...
...
src/interfaces/odbc/socket.c
View file @
296e7ba2
/* Module: socket.c
/*-------
* Module: socket.c
*
* Description: This module contains functions for low level socket
* operations (connecting/reading/writing to the backend)
...
...
@@ -8,7 +9,7 @@
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -42,6 +43,7 @@ SOCK_clear_error(SocketClass *self)
self
->
errormsg
=
NULL
;
}
SocketClass
*
SOCK_Constructor
()
{
...
...
@@ -70,16 +72,14 @@ SOCK_Constructor()
free
(
rv
);
return
NULL
;
}
rv
->
errormsg
=
NULL
;
rv
->
errornumber
=
0
;
rv
->
reverse
=
FALSE
;
}
return
rv
;
}
void
SOCK_Destructor
(
SocketClass
*
self
)
{
...
...
@@ -97,7 +97,6 @@ SOCK_Destructor(SocketClass *self)
free
(
self
->
buffer_out
);
free
(
self
);
}
...
...
@@ -149,7 +148,6 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
if
(
connect
(
self
->
socket
,
(
struct
sockaddr
*
)
&
(
sadr
),
sizeof
(
sadr
))
<
0
)
{
self
->
errornumber
=
SOCKET_COULD_NOT_CONNECT
;
self
->
errormsg
=
"Could not connect to remote socket."
;
closesocket
(
self
->
socket
);
...
...
@@ -194,9 +192,10 @@ 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
SOCK_get_string
(
SocketClass
*
self
,
char
*
buffer
,
int
bufsize
)
{
...
...
@@ -297,15 +296,16 @@ SOCK_flush_output(SocketClass *self)
self
->
buffer_filled_out
=
0
;
}
unsigned
char
SOCK_get_next_byte
(
SocketClass
*
self
)
{
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_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
++
];
}
void
SOCK_put_next_byte
(
SocketClass
*
self
,
unsigned
char
next_byte
)
{
...
...
src/interfaces/odbc/statement.c
View file @
296e7ba2
/* Module: statement.c
/*-------
* Module: statement.c
*
* Description: This module contains functions related to creating
* and manipulating a statement.
...
...
@@ -8,7 +9,7 @@
* API functions: SQLAllocStmt, SQLFreeStmt
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -44,6 +45,7 @@ extern GLOBAL_VALUES globals;
#endif
#define PRN_NULLCHECK
/* Map sql commands to statement types */
static
struct
{
...
...
@@ -126,12 +128,9 @@ SQLAllocStmt(HDBC hdbc,
*
phstmt
=
(
HSTMT
)
stmt
;
/*
* Copy default statement options based from Connection options
*/
/* Copy default statement options based from Connection options */
stmt
->
options
=
conn
->
stmtOptions
;
/* Save the handle for later */
stmt
->
phstmt
=
phstmt
;
...
...
@@ -180,29 +179,27 @@ SQLFreeStmt(HSTMT hstmt,
/* Destroy the statement and free any results, cursors, etc. */
SC_Destructor
(
stmt
);
}
else
if
(
fOption
==
SQL_UNBIND
)
{
SC_unbind_cols
(
stmt
);
}
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
))
{
/* errormsg passed in above */
SC_log_error
(
func
,
""
,
stmt
);
return
SQL_ERROR
;
}
}
else
if
(
fOption
==
SQL_RESET_PARAMS
)
{
SC_free_params
(
stmt
,
STMT_FREE_PARAMS_ALL
);
}
else
{
...
...
@@ -216,8 +213,7 @@ SQLFreeStmt(HSTMT hstmt,
}
/**********************************************************************
/*
* StatementClass implementation
*/
void
...
...
@@ -234,6 +230,7 @@ InitializeStatementOptions(StatementOptions *opt)
opt
->
use_bookmarks
=
SQL_UB_OFF
;
}
StatementClass
*
SC_Constructor
(
void
)
{
...
...
@@ -288,7 +285,6 @@ SC_Constructor(void)
rv
->
nfld
=
0
;
rv
->
parse_status
=
STMT_PARSE_NONE
;
/* Clear Statement Options -- defaults will be set in AllocStmt */
memset
(
&
rv
->
options
,
0
,
sizeof
(
StatementOptions
));
...
...
@@ -298,10 +294,10 @@ SC_Constructor(void)
return
rv
;
}
char
SC_Destructor
(
StatementClass
*
self
)
{
mylog
(
"SC_Destructor: self=%u, self->result=%u, self->hdbc=%u
\n
"
,
self
,
self
->
result
,
self
->
hdbc
);
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
* driver
*/
/*
* by by the application that uses that driver, so we don't have to
* driver but by the application that uses that driver, so we don't have to
* care
*/
/* about that here. */
if
(
self
->
bindings
)
free
(
self
->
bindings
);
/* Free the parsed table information */
if
(
self
->
ti
)
{
...
...
@@ -358,7 +349,6 @@ SC_Destructor(StatementClass *self)
free
(
self
->
fi
);
}
free
(
self
);
mylog
(
"SC_Destructor: EXIT
\n
"
);
...
...
@@ -366,9 +356,11 @@ SC_Destructor(StatementClass *self)
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
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
].
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
from SQLFreeStmt(SQL_CLOSE)
/*
* Called from SQLPrepare if STMT_PREMATURE, or
* from SQLExecute if STMT_FINISHED, or
* from SQLFreeStmt(SQL_CLOSE)
*/
char
SC_recycle_statement
(
StatementClass
*
self
)
...
...
@@ -472,7 +464,6 @@ SC_recycle_statement(StatementClass *self)
conn
=
SC_get_conn
(
self
);
if
(
!
CC_is_in_autocommit
(
conn
)
&&
CC_is_in_trans
(
conn
))
{
QResultClass
*
res
=
CC_send_query
(
conn
,
"ABORT"
,
NULL
);
QR_Destructor
(
res
);
...
...
@@ -523,10 +514,9 @@ SC_recycle_statement(StatementClass *self)
}
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
->
manual_result
=
FALSE
;
/* very important */
...
...
@@ -542,14 +532,17 @@ SC_recycle_statement(StatementClass *self)
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 */
/* the next SQLParamData/SQLPutData is called. */
/*
* Free any data at exec params before the statement is executed
* 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
);
return
TRUE
;
}
/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
void
SC_pre_execute
(
StatementClass
*
self
)
...
...
@@ -586,6 +579,7 @@ SC_pre_execute(StatementClass *self)
}
}
/* This is only called from SQLFreeStmt(SQL_UNBIND) */
char
SC_unbind_cols
(
StatementClass
*
self
)
...
...
@@ -607,6 +601,7 @@ SC_unbind_cols(StatementClass *self)
return
1
;
}
void
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
*
SC_create_errormsg
(
StatementClass
*
self
)
{
...
...
@@ -654,12 +651,13 @@ SC_create_errormsg(StatementClass *self)
return
msg
;
}
char
SC_get_error
(
StatementClass
*
self
,
int
*
number
,
char
**
message
)
{
char
rv
;
/* Create a very informative errormsg if it hasn't been done yet. */
/* Create a very informative errormsg if it hasn't been done yet. */
if
(
!
self
->
errormsg_created
)
{
self
->
errormsg
=
SC_create_errormsg
(
self
);
...
...
@@ -679,16 +677,19 @@ SC_get_error(StatementClass *self, int *number, char **message)
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
SC_get_bookmark
(
StatementClass
*
self
)
{
return
(
self
->
currTuple
+
1
);
}
RETCODE
SC_fetch
(
StatementClass
*
self
)
{
...
...
@@ -702,7 +703,7 @@ SC_fetch(StatementClass *self)
char
*
value
;
ColumnInfoClass
*
ci
;
/* TupleField *tupleField; */
/* TupleField *tupleField; */
self
->
last_fetch_count
=
0
;
ci
=
QR_get_fields
(
res
);
/* the column info */
...
...
@@ -711,11 +712,9 @@ SC_fetch(StatementClass *self)
if
(
self
->
manual_result
||
!
globals
.
use_declarefetch
)
{
if
(
self
->
currTuple
>=
QR_get_num_tuples
(
res
)
-
1
||
(
self
->
options
.
maxRows
>
0
&&
self
->
currTuple
==
self
->
options
.
maxRows
-
1
))
{
/*
* if at the end of the tuples, return "no data found" and set
* the cursor past the end of the result set
...
...
@@ -729,7 +728,6 @@ SC_fetch(StatementClass *self)
}
else
{
/* read from the cache or the physical next tuple */
retval
=
QR_next_tuple
(
res
);
if
(
retval
<
0
)
...
...
@@ -739,7 +737,6 @@ SC_fetch(StatementClass *self)
}
else
if
(
retval
>
0
)
(
self
->
currTuple
)
++
;
/* all is well */
else
{
mylog
(
"SQLFetch: error
\n
"
);
...
...
@@ -772,7 +769,6 @@ SC_fetch(StatementClass *self)
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
);
/* reset for SQLGetData */
...
...
@@ -828,13 +824,13 @@ SC_fetch(StatementClass *self)
result
=
SQL_SUCCESS_WITH_INFO
;
break
;
case
COPY_GENERAL_ERROR
:
/* error msg already
* filled in */
/* error msg already filled in */
case
COPY_GENERAL_ERROR
:
SC_log_error
(
func
,
""
,
self
);
result
=
SQL_ERROR
;
break
;
/* This would not be meaningful in SQLFetch. */
/* This would not be meaningful in SQLFetch. */
case
COPY_NO_DATA_FOUND
:
break
;
...
...
@@ -908,13 +904,10 @@ SC_execute(StatementClass *self)
CC_set_in_trans
(
conn
);
}
oldstatus
=
conn
->
status
;
conn
->
status
=
CONN_EXECUTING
;
self
->
status
=
STMT_EXECUTING
;
/* If it's a SELECT statement, use a cursor. */
/*
...
...
@@ -924,19 +917,16 @@ SC_execute(StatementClass *self)
/* in copy_statement... */
if
(
self
->
statement_type
==
STMT_TYPE_SELECT
)
{
char
fetch
[
128
];
mylog
(
" Sending SELECT statement on stmt=%u, cursor_name='%s'
\n
"
,
self
,
self
->
cursor_name
);
/* send the declare/select */
self
->
result
=
CC_send_query
(
conn
,
self
->
stmt_with_params
,
NULL
);
if
(
globals
.
use_declarefetch
&&
self
->
result
!=
NULL
&&
QR_command_successful
(
self
->
result
))
{
QR_Destructor
(
self
->
result
);
/*
...
...
@@ -954,20 +944,15 @@ SC_execute(StatementClass *self)
* will correct for any discrepancies in sizes and adjust the
* cache accordingly.
*/
sprintf
(
fetch
,
"fetch %d in %s"
,
qi
.
row_size
,
self
->
cursor_name
);
self
->
result
=
CC_send_query
(
conn
,
fetch
,
&
qi
);
}
mylog
(
" done sending the query:
\n
"
);
}
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
);
self
->
result
=
CC_send_query
(
conn
,
self
->
stmt_with_params
,
NULL
);
...
...
@@ -986,7 +971,6 @@ SC_execute(StatementClass *self)
QR_Destructor
(
res
);
CC_set_no_trans
(
conn
);
}
}
conn
->
status
=
oldstatus
;
...
...
@@ -995,7 +979,6 @@ SC_execute(StatementClass *self)
/* Check the status of the result */
if
(
self
->
result
)
{
was_ok
=
QR_command_successful
(
self
->
result
);
was_nonfatal
=
QR_command_nonfatal
(
self
->
result
);
...
...
@@ -1004,8 +987,8 @@ SC_execute(StatementClass *self)
else
self
->
errornumber
=
was_nonfatal
?
STMT_INFO_ONLY
:
STMT_ERROR_TAKEN_FROM_BACKEND
;
self
->
currTuple
=
-
1
;
/* set cursor before the first tuple in
* the list */
/* set cursor before the first tuple in the list */
self
->
currTuple
=
-
1
;
self
->
current_col
=
-
1
;
self
->
rowset_start
=
-
1
;
...
...
@@ -1029,9 +1012,8 @@ SC_execute(StatementClass *self)
CC_abort
(
conn
);
}
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
)
{
self
->
errornumber
=
STMT_CREATE_TABLE_ERROR
;
...
...
@@ -1069,6 +1051,7 @@ SC_execute(StatementClass *self)
}
}
void
SC_log_error
(
char
*
func
,
char
*
desc
,
StatementClass
*
self
)
{
...
...
src/interfaces/odbc/tuple.c
View file @
296e7ba2
/* Module: tuple.c
/*-------
* Module: tuple.c
*
* Description: This module contains functions for setting the data for individual
* fields (TupleField structure) of a manual result set.
* Description: This module contains functions for setting the data
* for individual fields (TupleField structure) of a
* manual result set.
*
* Important Note: These functions are ONLY used in building manual result sets for
* info functions (SQLTables, SQLColumns, etc.)
* Important Note: These functions are ONLY used in building manual
* result sets for info functions (SQLTables,
* SQLColumns, etc.)
*
* Classes: n/a
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
-------
*/
#include "tuple.h"
#include <string.h>
#include <stdlib.h>
void
set_tuplefield_null
(
TupleField
*
tuple_field
)
{
...
...
@@ -25,6 +29,7 @@ set_tuplefield_null(TupleField *tuple_field)
tuple_field
->
value
=
NULL
;
/* strdup(""); */
}
void
set_tuplefield_string
(
TupleField
*
tuple_field
,
char
*
string
)
{
...
...
@@ -39,7 +44,6 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
{
char
buffer
[
10
];
sprintf
(
buffer
,
"%d"
,
value
);
tuple_field
->
len
=
strlen
(
buffer
)
+
1
;
...
...
@@ -47,6 +51,7 @@ set_tuplefield_int2(TupleField *tuple_field, Int2 value)
tuple_field
->
value
=
strdup
(
buffer
);
}
void
set_tuplefield_int4
(
TupleField
*
tuple_field
,
Int4
value
)
{
...
...
src/interfaces/odbc/tuplelist.c
View file @
296e7ba2
/* Module: tuplelist.c
/*--------
* Module: tuplelist.c
*
* Description: This module contains functions for creating a manual result set
* (the TupleList) and retrieving data from it for a specific row/column.
* Description: This module contains functions for creating a manual
* result set (the TupleList) and retrieving data from
* it for a specific row/column.
*
* Classes: TupleListClass (Functions prefix: "TL_")
*
* API functions: none
*
* Comments: See "notice.txt" for copyright and license information.
*
*
--------
*/
#include <stdlib.h>
#include "tuplelist.h"
#include "tuple.h"
TupleListClass
*
TL_Constructor
(
UInt4
fieldcnt
)
{
...
...
@@ -25,7 +28,6 @@ TL_Constructor(UInt4 fieldcnt)
rv
=
(
TupleListClass
*
)
malloc
(
sizeof
(
TupleListClass
));
if
(
rv
)
{
rv
->
num_fields
=
fieldcnt
;
rv
->
num_tuples
=
0
;
rv
->
list_start
=
NULL
;
...
...
@@ -39,6 +41,7 @@ TL_Constructor(UInt4 fieldcnt)
return
rv
;
}
void
TL_Destructor
(
TupleListClass
*
self
)
{
...
...
@@ -134,7 +137,6 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
}
else
if
(
start_is_closer
)
{
/*
* the shortest way is to start the search from the head of the
* list
...
...
@@ -177,11 +179,9 @@ TL_get_fieldval(TupleListClass *self, Int4 tupleno, Int2 fieldno)
}
char
TL_add_tuple
(
TupleListClass
*
self
,
TupleNode
*
new_field
)
{
/*
* we append the tuple at the end of the doubly linked list of the
* tuples we have already read in
...
...
@@ -200,7 +200,6 @@ TL_add_tuple(TupleListClass *self, TupleNode *new_field)
}
else
{
/*
* there is already an element in the list, so add the new one at
* the end of the list
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment