mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Version 06-30-0248
This commit is contained in:
44
src/interfaces/odbc/Config.mk
Normal file
44
src/interfaces/odbc/Config.mk
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
#============ Default for all system ==============
|
||||||
|
OS = UNX
|
||||||
|
SHELL = /bin/sh
|
||||||
|
AR = ar r
|
||||||
|
DLSUFFIX= so
|
||||||
|
INCDIR = /include
|
||||||
|
OBJX =
|
||||||
|
RANLIB = ranlib
|
||||||
|
INSTALL = /usr/bin/install
|
||||||
|
INSTALL_DATA = $(INSTALL) -c -m 644
|
||||||
|
MKDIR = mkdir
|
||||||
|
DESTDIR = /usr/local
|
||||||
|
LIBDIR = /lib
|
||||||
|
INSTHEADERS = isql.h isqlext.h iodbc.h
|
||||||
|
DESTLIBDIR = $(DESTDIR)$(LIBDIR)
|
||||||
|
DESTINCDIR = $(DESTDIR)$(INCDIR)/iodbc
|
||||||
|
ODBCSYSTEMDIR = /usr/home/gryschuk
|
||||||
|
|
||||||
|
# Remove the comment characters from the section you want to
|
||||||
|
# use below, make sure all other sections are commented out.
|
||||||
|
|
||||||
|
#============== Linux ELF =========================
|
||||||
|
CC = gcc
|
||||||
|
PIC = -fPIC
|
||||||
|
CFLAGSX = -g
|
||||||
|
#CFLAGSX = -g -Wall -DMY_LOG -DQ_LOG
|
||||||
|
LDFLAGS = -shared
|
||||||
|
LIBS = -ldl
|
||||||
|
|
||||||
|
#============= FreeBSD 2.x ========================
|
||||||
|
# I don't know if this would work but you can always just try it.
|
||||||
|
# PIC = -fPIC
|
||||||
|
# CFLAGSX = -g -Wall
|
||||||
|
# LDFLAGS = -Bshareable
|
||||||
|
# LIBS =
|
||||||
|
|
||||||
|
#===| end of file 'Config.mk' |===
|
||||||
|
|
||||||
|
|
85
src/interfaces/odbc/Makefile.unx
Normal file
85
src/interfaces/odbc/Makefile.unx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
# .include "Version.mk"
|
||||||
|
# .include "Config.mk"
|
||||||
|
include Version.mk
|
||||||
|
include Config.mk
|
||||||
|
#==============================================================================
|
||||||
|
# Makefile
|
||||||
|
#
|
||||||
|
# UNIX Makefile to build the CLI for PostgreSQL/Postgres95
|
||||||
|
#
|
||||||
|
#==============================================================================
|
||||||
|
# Site specific configuration (UNIX)
|
||||||
|
#==============================================================================
|
||||||
|
#
|
||||||
|
# option switches
|
||||||
|
#
|
||||||
|
# debug: select this to enable debugging of the software
|
||||||
|
#DEBUG = -D_DEBUG
|
||||||
|
#
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
#---| definitions |------------------------------------------------------------
|
||||||
|
|
||||||
|
# NAME = cli
|
||||||
|
NAME = psqlodbc
|
||||||
|
|
||||||
|
OBJECTS = info.o bind.o columninfo.o connection.o convert.o drvconn.o \
|
||||||
|
environ.o execute.o lobj.o misc.o options.o \
|
||||||
|
pgtypes.o psqlodbc.o qresult.o results.o socket.o statement.o \
|
||||||
|
gpps.o tuple.o tuplelist.o dlg_specific.o $(OBJX)
|
||||||
|
|
||||||
|
#CFLAGS = -c $(DEBUG) -D$(PG_ENV) -O $(PIC) $(ANSI) -I$(PG_INCLUDE) \
|
||||||
|
# -I$(ODBC_INCLUDE) -D$(DLDAPI) $(CFLAGSX) -DHAVE_CONFIG_H \
|
||||||
|
# -DVERSION=\"$(VERSION)$(EXTVER)\"
|
||||||
|
CFLAGS = -g -c -Wall $(DEBUG) -O $(PIC) $(ANSI) -I. -I.. \
|
||||||
|
-I$(PG_INCLUDE) -I$(ODBC_INCLUDE) $(CFLAGSX) -DHAVE_CONFIG_H
|
||||||
|
|
||||||
|
shlib = lib$(NAME)-$(VERSION).$(DLSUFFIX)
|
||||||
|
DESTDIR = /usr/local
|
||||||
|
LIBDIR = /lib
|
||||||
|
|
||||||
|
#---| global dependencies |----------------------------------------------------
|
||||||
|
|
||||||
|
#all: $(OBJECTS) lib dll
|
||||||
|
|
||||||
|
all: $(OBJECTS) dll
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f core *.o *~ *.core
|
||||||
|
|
||||||
|
delete: clean
|
||||||
|
|
||||||
|
delete_all: delete
|
||||||
|
-rm -f /usr/local/lib/lib$(NAME)_$(MSQL_ENV).a
|
||||||
|
-rm -f /usr/local/lib/lib$(NAME)_$(MSQL_ENV).$(DLSUFFIX)
|
||||||
|
|
||||||
|
#---| local dependencies |-----------------------------------------------------
|
||||||
|
#log.o: ../SRC_LOG/log.c ../SRC_LOG/log.h
|
||||||
|
# $(CC) $(CFLAGS) -I../SRC_LOG ../SRC_LOG/log.c
|
||||||
|
|
||||||
|
lib:
|
||||||
|
$(AR) lib$(NAME)$(PG_ENV).a $(OBJECTS)
|
||||||
|
$(RANLIB) lib$(NAME)$(PG_ENV).a
|
||||||
|
|
||||||
|
dll: $(OBJECTS)
|
||||||
|
$(LD) $(LDFLAGS) -L$(PG_LIBPATH) $(OBJECTS) \
|
||||||
|
-o $(shlib) $(LIBS) $(PG_LIBS)
|
||||||
|
|
||||||
|
install-shlib: $(shlib)
|
||||||
|
$(INSTALL_DATA) $(shlib) $(DESTDIR)$(LIBDIR)/$(shlib)
|
||||||
|
rm -f $(DESTDIR)$(LIBDIR)/lib$(NAME).so
|
||||||
|
ln -sf $(shlib) $(DESTDIR)$(LIBDIR)/lib$(NAME).so
|
||||||
|
|
||||||
|
install-headers: $(INSTHEADERS)
|
||||||
|
if [ -d $(DESTDIR)$(INCDIR)/iodbc ]; then : ; else $(MKDIR) $(DESTDIR)$(INCDIR)/iodbc; fi
|
||||||
|
$(INSTALL_DATA) $(INSTHEADERS) $(DESTDIR)$(INCDIR)/iodbc
|
||||||
|
|
||||||
|
install-ini: odbcinst.ini
|
||||||
|
$(INSTALL_DATA) odbcinst.ini /etc
|
||||||
|
|
||||||
|
install: install-headers install-shlib install-ini
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
|
113
src/interfaces/odbc/README.Linux
Normal file
113
src/interfaces/odbc/README.Linux
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
Unix port of psqlodbc, brought to you by:
|
||||||
|
Gerald Gryschuk(ggryschuk@home.com)
|
||||||
|
|
||||||
|
This is the first release of a port of psqlodbc to Unix(specifically Linux),
|
||||||
|
as such the installation may not be as straight forward as it could be(then
|
||||||
|
again it might be). As well the only testing of the driver has been with
|
||||||
|
the real project I'm working on, since it seems to be working there I assumed
|
||||||
|
it was ready to go out. This port works with Ke Jin's iodbc driver manager
|
||||||
|
although there is no theoretical reason why it couldn't work with other
|
||||||
|
driver managers for UNIX(I know of none though). The FreeODBC site
|
||||||
|
(http://users.ids.net/~bjepson/freeODBC/) has a link to download the current
|
||||||
|
version of iodbc(iodbc-2.12).
|
||||||
|
|
||||||
|
This driver has been successfully compiled and tested on a RedHat 4.1 system
|
||||||
|
using both gcc 2.7.2 and egcs 1.0.2.
|
||||||
|
|
||||||
|
INSTALLATION:
|
||||||
|
|
||||||
|
If you have a system any where close to mine this will be easy, just
|
||||||
|
copy Makefile.lnx to Makefile then type 'make' and see what happens. Note
|
||||||
|
that if you have not enabled logging(read the file misc.h) then you
|
||||||
|
may get alot of warning messages, just ignore these, they shouldn't be
|
||||||
|
a problem. If this doesn't work, well... I don't know what to say, see if
|
||||||
|
you can figure out what's wrong,fix it and send me a message. If everything
|
||||||
|
makes o.k. you can 'make install' which will install the shared library
|
||||||
|
(in /usr/local/lib) and a WINDOWS type INI file in /etc (called odbcinst.ini,
|
||||||
|
see CONFIGURATION below). If you want to program using this driver do a
|
||||||
|
'make install-headers' which will install programming header files in
|
||||||
|
/usr/local/include/iodbc. If you don't like these install locations edit
|
||||||
|
Config.mk and change the environment variable DESTDIR(and possible DESTINCDIR
|
||||||
|
to get rid of the /iodbc) to suit your system.
|
||||||
|
|
||||||
|
CONFIGURATION:
|
||||||
|
|
||||||
|
The psqlodbc driver reads two Windows type INI files for configuration,
|
||||||
|
one called odbcinst.ini located in /etc which is used for system wide
|
||||||
|
configuration of the driver and one in the users home directory called
|
||||||
|
.odbc.ini, which can be used to override the system wide settings. Note that
|
||||||
|
the location of odbcinst is currently hardcoded into the source so if you
|
||||||
|
want to change this you have to change it in the source as well. This latter
|
||||||
|
file is also searched for by iodbc and is where
|
||||||
|
the DataSource definitions are placed. The format of both files is exactly
|
||||||
|
like that of a Windows INI file using key,value pairs. A DataSource definition
|
||||||
|
is started with a section name enclosed in square brackets i.e. [PostODBC].
|
||||||
|
Comments are started using a ';' character and are restricted to being
|
||||||
|
only on seperate lines(i.e. no comments are allowed on definition lines).
|
||||||
|
The important keywords for psqlodbc are:
|
||||||
|
Driver = (location where the psqlodbc library was installed)
|
||||||
|
ex. Driver = /usr/local/lib/libpspqlodbc.so
|
||||||
|
|
||||||
|
ServerName = hostname or ip-address of postgreSQL server
|
||||||
|
ex. ServerName = simpsons.springfield.com
|
||||||
|
or ServerName = 192.1.1.1
|
||||||
|
|
||||||
|
Database = name of database to connect to
|
||||||
|
ex. Database = template1
|
||||||
|
|
||||||
|
Port = tcp port that the postgreSQL server is listening on, note
|
||||||
|
that this need not be set as the driver defaults to the
|
||||||
|
default postgreSQL port of 5432. Of course if your server
|
||||||
|
is listening on a different port than you need to say
|
||||||
|
what it is here.
|
||||||
|
|
||||||
|
Username = name of authorized postgreSQL user
|
||||||
|
ex. Username = homer
|
||||||
|
|
||||||
|
Password = the password for the user named in Username. Note
|
||||||
|
that if you have password checking on in postgreSQL
|
||||||
|
you have to have this field. Unfortunately this means
|
||||||
|
storing clear text passwords in a file. If this bothers
|
||||||
|
you, well... write a dialog box routine and send it
|
||||||
|
to me.
|
||||||
|
ex. Password = Doh!
|
||||||
|
|
||||||
|
ReadOnly = 0 or 1. Default is 1 => database IS readonly. If
|
||||||
|
set to 0, database is read-write.
|
||||||
|
ex. ReadOnly = 0
|
||||||
|
|
||||||
|
Protocol = 6.2 to force the use of Postgres 6.2 protocol
|
||||||
|
|
||||||
|
The odbcinst.ini file is where sytem wide settings are kept. There are
|
||||||
|
quite a number of these, all of which have built-in defaults. Since I'm
|
||||||
|
not even sure what they are all for I won't try to describe them, check
|
||||||
|
the file dlg_specific.h for a list and some explanation. Two that I found
|
||||||
|
useful are Debug and CommLog, which can be used to tailor logging of messages
|
||||||
|
by the driver(note that you have to have defined MY_LOG and Q_LOG during
|
||||||
|
compilation of the driver, see the file misc.h for an explanation). If
|
||||||
|
you have logging On(ie. CommLog = 1 and/or Debug = 1) then logging will
|
||||||
|
occur to the files /tmp/mylog.log(Debug, only developers will be
|
||||||
|
interested) and /tmp/psqlodbc.log(end user log file).
|
||||||
|
|
||||||
|
USE:
|
||||||
|
run an ODBC enabled application :-) .
|
||||||
|
|
||||||
|
O.k. Well, the only ODBC compliant applications that I can
|
||||||
|
"guarantee" to work are those that are compiled using the following
|
||||||
|
headers that come with this driver, iodbc.h, isql.h and isqlext.h.
|
||||||
|
|
||||||
|
BUGS,etc.
|
||||||
|
|
||||||
|
If you have problems with compiling/installing or making this
|
||||||
|
package send e-mail to me at:
|
||||||
|
gerald.gryschuk@home.com or to the pgsql-interfaces mailing list
|
||||||
|
pgsql-interfaces@postgresql.org .
|
||||||
|
|
||||||
|
Ports to different Unices are greatly appreciated and can probably be
|
||||||
|
sent to me for now(although this may change shortly).
|
||||||
|
|
||||||
|
Bugs of a general nature should still be sent to the current
|
||||||
|
maintainer or to the interfaces list.
|
||||||
|
|
||||||
|
|
3
src/interfaces/odbc/Version.mk
Normal file
3
src/interfaces/odbc/Version.mk
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
VERSION = 0.24
|
||||||
|
EXTVER = .2
|
||||||
|
|
@ -12,6 +12,11 @@
|
|||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "bind.h"
|
#include "bind.h"
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
@ -19,8 +24,15 @@
|
|||||||
#include "pgtypes.h"
|
#include "pgtypes.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Bind parameters on a statement handle
|
// Bind parameters on a statement handle
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
ColumnInfoClass *
|
ColumnInfoClass *
|
||||||
CI_Constructor()
|
CI_Constructor()
|
||||||
|
5
src/interfaces/odbc/config.h
Normal file
5
src/interfaces/odbc/config.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#define HAVE_IODBC 1
|
||||||
|
#define UNIX 1
|
||||||
|
#define HAVE_PARAM_H 1
|
||||||
|
#define HAVE_PWD_H 1
|
||||||
|
#define HAVE_STRICMP 0
|
@ -21,7 +21,11 @@
|
|||||||
#include "lobj.h"
|
#include "lobj.h"
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef UNIX
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STMT_INCREMENT 16 /* how many statement holders to allocate at a time */
|
#define STMT_INCREMENT 16 /* how many statement holders to allocate at a time */
|
||||||
|
|
||||||
@ -99,7 +103,7 @@ char *func = "SQLConnect";
|
|||||||
/* fill in any defaults */
|
/* fill in any defaults */
|
||||||
getDSNdefaults(ci);
|
getDSNdefaults(ci);
|
||||||
|
|
||||||
qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", ci->dsn, ci->username, ci->password);
|
qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", conn, ci->dsn, ci->username, ci->password);
|
||||||
|
|
||||||
if ( CC_connect(conn, FALSE) <= 0) {
|
if ( CC_connect(conn, FALSE) <= 0) {
|
||||||
// Error messages are filled in
|
// Error messages are filled in
|
||||||
@ -229,6 +233,14 @@ ConnectionClass *rv;
|
|||||||
rv->num_stmts = STMT_INCREMENT;
|
rv->num_stmts = STMT_INCREMENT;
|
||||||
|
|
||||||
rv->lobj_type = PG_TYPE_LO;
|
rv->lobj_type = PG_TYPE_LO;
|
||||||
|
|
||||||
|
rv->ntables = 0;
|
||||||
|
rv->col_info = NULL;
|
||||||
|
|
||||||
|
rv->translation_option = 0;
|
||||||
|
rv->translation_handle = NULL;
|
||||||
|
rv->DataSourceToDriver = NULL;
|
||||||
|
rv->DriverToDataSource = NULL;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -254,6 +266,19 @@ CC_Destructor(ConnectionClass *self)
|
|||||||
}
|
}
|
||||||
mylog("after free statement holders\n");
|
mylog("after free statement holders\n");
|
||||||
|
|
||||||
|
/* Free cached table info */
|
||||||
|
if (self->col_info) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < self->ntables; i++) {
|
||||||
|
if (self->col_info[i]->result) /* Free the SQLColumns result structure */
|
||||||
|
QR_Destructor(self->col_info[i]->result);
|
||||||
|
|
||||||
|
free(self->col_info[i]);
|
||||||
|
}
|
||||||
|
free(self->col_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
free(self);
|
free(self);
|
||||||
|
|
||||||
mylog("exit CC_Destructor\n");
|
mylog("exit CC_Destructor\n");
|
||||||
@ -354,11 +379,54 @@ StatementClass *stmt;
|
|||||||
self->stmts[i] = NULL;
|
self->stmts[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for translation dll */
|
||||||
|
if ( self->translation_handle) {
|
||||||
|
FreeLibrary (self->translation_handle);
|
||||||
|
self->translation_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mylog("exit CC_Cleanup\n");
|
mylog("exit CC_Cleanup\n");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CC_set_translation (ConnectionClass *self)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (self->translation_handle != NULL) {
|
||||||
|
FreeLibrary (self->translation_handle);
|
||||||
|
self->translation_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->connInfo.translation_dll[0] == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
self->translation_option = atoi (self->connInfo.translation_option);
|
||||||
|
self->translation_handle = LoadLibrary (self->connInfo.translation_dll);
|
||||||
|
|
||||||
|
if (self->translation_handle == NULL) {
|
||||||
|
self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
|
||||||
|
self->errormsg = "Could not load the translation DLL.";
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->DataSourceToDriver
|
||||||
|
= (DataSourceToDriverProc) GetProcAddress (self->translation_handle,
|
||||||
|
"SQLDataSourceToDriver");
|
||||||
|
|
||||||
|
self->DriverToDataSource
|
||||||
|
= (DriverToDataSourceProc) GetProcAddress (self->translation_handle,
|
||||||
|
"SQLDriverToDataSource");
|
||||||
|
|
||||||
|
if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) {
|
||||||
|
self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
|
||||||
|
self->errormsg = "Could not find translation DLL functions.";
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
CC_connect(ConnectionClass *self, char do_password)
|
CC_connect(ConnectionClass *self, char do_password)
|
||||||
@ -587,15 +655,17 @@ char salt[2];
|
|||||||
|
|
||||||
mylog("empty query seems to be OK.\n");
|
mylog("empty query seems to be OK.\n");
|
||||||
|
|
||||||
|
CC_set_translation (self);
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
/******* Send any initial settings *********/
|
/******* Send any initial settings *********/
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
|
|
||||||
// The Unix iodbc errors out on this call because it allocates a statement
|
/* Since these functions allocate statements, and since the connection is not
|
||||||
// before the connection is established. Therefore, don't check for error here.
|
established yet, it would violate odbc state transition rules. Therefore,
|
||||||
|
these functions call the corresponding local function instead.
|
||||||
|
*/
|
||||||
CC_send_settings(self);
|
CC_send_settings(self);
|
||||||
|
|
||||||
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
|
CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
|
||||||
|
|
||||||
// CC_test(self);
|
// CC_test(self);
|
||||||
@ -1074,6 +1144,7 @@ int i;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char
|
char
|
||||||
CC_send_settings(ConnectionClass *self)
|
CC_send_settings(ConnectionClass *self)
|
||||||
{
|
{
|
||||||
@ -1085,7 +1156,10 @@ StatementClass *stmt;
|
|||||||
RETCODE result;
|
RETCODE result;
|
||||||
SWORD cols = 0;
|
SWORD cols = 0;
|
||||||
|
|
||||||
result = SQLAllocStmt( self, &hstmt);
|
/* 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)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -1116,13 +1190,13 @@ SWORD cols = 0;
|
|||||||
if (ini_query[0] != '\0') {
|
if (ini_query[0] != '\0') {
|
||||||
mylog("Sending Initial Connection query: '%s'\n", ini_query);
|
mylog("Sending Initial Connection query: '%s'\n", ini_query);
|
||||||
|
|
||||||
result = SQLExecDirect(hstmt, ini_query, SQL_NTS);
|
result = _SQLExecDirect(hstmt, ini_query, SQL_NTS);
|
||||||
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
SQLFreeStmt(hstmt, SQL_DROP);
|
_SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLFreeStmt(hstmt, SQL_DROP);
|
_SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1139,36 +1213,39 @@ HSTMT hstmt;
|
|||||||
StatementClass *stmt;
|
StatementClass *stmt;
|
||||||
RETCODE result;
|
RETCODE result;
|
||||||
|
|
||||||
result = SQLAllocStmt( self, &hstmt);
|
/* 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)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stmt = (StatementClass *) hstmt;
|
stmt = (StatementClass *) hstmt;
|
||||||
|
|
||||||
result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" \
|
result = _SQLExecDirect(hstmt, "select oid from pg_type where typname='" \
|
||||||
PG_TYPE_LO_NAME \
|
PG_TYPE_LO_NAME \
|
||||||
"'", SQL_NTS);
|
"'", SQL_NTS);
|
||||||
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
SQLFreeStmt(hstmt, SQL_DROP);
|
_SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SQLFetch(hstmt);
|
result = _SQLFetch(hstmt);
|
||||||
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
SQLFreeStmt(hstmt, SQL_DROP);
|
_SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
|
result = _SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
|
||||||
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
SQLFreeStmt(hstmt, SQL_DROP);
|
_SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("Got the large object oid: %d\n", self->lobj_type);
|
mylog("Got the large object oid: %d\n", self->lobj_type);
|
||||||
qlog(" [ Large Object oid = %d ]\n", self->lobj_type);
|
qlog(" [ Large Object oid = %d ]\n", self->lobj_type);
|
||||||
|
|
||||||
result = SQLFreeStmt(hstmt, SQL_DROP);
|
result = _SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1201,29 +1278,38 @@ RETCODE result;
|
|||||||
SDWORD pcbValue;
|
SDWORD pcbValue;
|
||||||
UDWORD pcrow;
|
UDWORD pcrow;
|
||||||
UWORD rgfRowStatus;
|
UWORD rgfRowStatus;
|
||||||
char buf[255];
|
char name[255], type[255];
|
||||||
SDWORD buflen;
|
SDWORD namelen, typelen;
|
||||||
DATE_STRUCT *ds;
|
SWORD cols;
|
||||||
|
|
||||||
result = SQLAllocStmt( self, &hstmt1);
|
result = SQLAllocStmt( self, &hstmt1);
|
||||||
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = SQLExecDirect(hstmt1, "select * from cpar", SQL_NTS);
|
result = SQLTables(hstmt1, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS);
|
||||||
qlog("exec result = %d\n", result);
|
qlog("SQLTables result = %d\n", result);
|
||||||
|
|
||||||
result = SQLBindCol(hstmt1, 2, SQL_C_DATE, buf, 0, &buflen);
|
result = SQLNumResultCols(hstmt1, &cols);
|
||||||
|
qlog("cols SQLTables result = %d\n", result);
|
||||||
|
|
||||||
|
result = SQLBindCol(hstmt1, 3, SQL_C_CHAR, name, sizeof(name), &namelen);
|
||||||
qlog("bind result = %d\n", result);
|
qlog("bind result = %d\n", result);
|
||||||
|
|
||||||
|
result = SQLBindCol(hstmt1, 4, SQL_C_CHAR, type, sizeof(type), &typelen);
|
||||||
|
qlog("bind result = %d\n", result);
|
||||||
|
|
||||||
result = SQLFetch(hstmt1);
|
result = SQLFetch(hstmt1);
|
||||||
|
qlog("SQLFetch result = %d\n", result);
|
||||||
while (result != SQL_NO_DATA_FOUND) {
|
while (result != SQL_NO_DATA_FOUND) {
|
||||||
ds = (DATE_STRUCT *) buf;
|
qlog("fetch on stmt1: result=%d, namelen=%d: name='%s', typelen=%d, type='%s'\n", result, namelen, name, typelen, type);
|
||||||
qlog("fetch on stmt1: result=%d, buflen=%d: year=%d, month=%d, day=%d\n", result, buflen, ds->year, ds->month, ds->day);
|
|
||||||
|
|
||||||
result = SQLFetch(hstmt1);
|
result = SQLFetch(hstmt1);
|
||||||
}
|
}
|
||||||
|
qlog("SQLFetch result = %d\n", result);
|
||||||
SQLFreeStmt(hstmt1, SQL_DROP);
|
SQLFreeStmt(hstmt1, SQL_DROP);
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,9 +10,20 @@
|
|||||||
#ifndef __CONNECTION_H__
|
#ifndef __CONNECTION_H__
|
||||||
#define __CONNECTION_H__
|
#define __CONNECTION_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -48,6 +59,7 @@ typedef enum {
|
|||||||
#define CONN_NOT_IMPLEMENTED_ERROR 9
|
#define CONN_NOT_IMPLEMENTED_ERROR 9
|
||||||
#define CONN_INVALID_AUTHENTICATION 10
|
#define CONN_INVALID_AUTHENTICATION 10
|
||||||
#define CONN_AUTH_TYPE_UNSUPPORTED 11
|
#define CONN_AUTH_TYPE_UNSUPPORTED 11
|
||||||
|
#define CONN_UNABLE_TO_LOAD_DLL 12
|
||||||
|
|
||||||
|
|
||||||
/* Conn_status defines */
|
/* Conn_status defines */
|
||||||
@ -83,7 +95,7 @@ typedef enum {
|
|||||||
#define NO_AUTHENTICATION 7
|
#define NO_AUTHENTICATION 7
|
||||||
#define PATH_SIZE 64
|
#define PATH_SIZE 64
|
||||||
#define ARGV_SIZE 64
|
#define ARGV_SIZE 64
|
||||||
#define NAMEDATALEN 32
|
#define NAMEDATALEN 16
|
||||||
|
|
||||||
typedef unsigned int ProtocolVersion;
|
typedef unsigned int ProtocolVersion;
|
||||||
|
|
||||||
@ -130,11 +142,12 @@ typedef struct {
|
|||||||
char protocol[SMALL_REGISTRY_LEN];
|
char protocol[SMALL_REGISTRY_LEN];
|
||||||
char port[SMALL_REGISTRY_LEN];
|
char port[SMALL_REGISTRY_LEN];
|
||||||
char readonly[SMALL_REGISTRY_LEN];
|
char readonly[SMALL_REGISTRY_LEN];
|
||||||
// char unknown_sizes[SMALL_REGISTRY_LEN];
|
|
||||||
char fake_oid_index[SMALL_REGISTRY_LEN];
|
char fake_oid_index[SMALL_REGISTRY_LEN];
|
||||||
char show_oid_column[SMALL_REGISTRY_LEN];
|
char show_oid_column[SMALL_REGISTRY_LEN];
|
||||||
char row_versioning[SMALL_REGISTRY_LEN];
|
char row_versioning[SMALL_REGISTRY_LEN];
|
||||||
char show_system_tables[SMALL_REGISTRY_LEN];
|
char show_system_tables[SMALL_REGISTRY_LEN];
|
||||||
|
char translation_dll[MEDIUM_REGISTRY_LEN];
|
||||||
|
char translation_option[SMALL_REGISTRY_LEN];
|
||||||
char focus_password;
|
char focus_password;
|
||||||
} ConnInfo;
|
} ConnInfo;
|
||||||
|
|
||||||
@ -143,6 +156,35 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This is used to store cached table information in the connection */
|
||||||
|
struct col_info {
|
||||||
|
QResultClass *result;
|
||||||
|
char name[MAX_TABLE_LEN+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Translation DLL entry points */
|
||||||
|
typedef BOOL (FAR WINAPI *DataSourceToDriverProc) (UDWORD,
|
||||||
|
SWORD,
|
||||||
|
PTR,
|
||||||
|
SDWORD,
|
||||||
|
PTR,
|
||||||
|
SDWORD,
|
||||||
|
SDWORD FAR *,
|
||||||
|
UCHAR FAR *,
|
||||||
|
SWORD,
|
||||||
|
SWORD FAR *);
|
||||||
|
|
||||||
|
typedef BOOL (FAR WINAPI *DriverToDataSourceProc) (UDWORD,
|
||||||
|
SWORD,
|
||||||
|
PTR,
|
||||||
|
SDWORD,
|
||||||
|
PTR,
|
||||||
|
SDWORD,
|
||||||
|
SDWORD FAR *,
|
||||||
|
UCHAR FAR *,
|
||||||
|
SWORD,
|
||||||
|
SWORD FAR *);
|
||||||
|
|
||||||
/******* The Connection handle ************/
|
/******* The Connection handle ************/
|
||||||
struct ConnectionClass_ {
|
struct ConnectionClass_ {
|
||||||
HENV henv; /* environment this connection was created on */
|
HENV henv; /* environment this connection was created on */
|
||||||
@ -154,6 +196,12 @@ struct ConnectionClass_ {
|
|||||||
int num_stmts;
|
int num_stmts;
|
||||||
SocketClass *sock;
|
SocketClass *sock;
|
||||||
int lobj_type;
|
int lobj_type;
|
||||||
|
int ntables;
|
||||||
|
COL_INFO **col_info;
|
||||||
|
long translation_option;
|
||||||
|
HINSTANCE translation_handle;
|
||||||
|
DataSourceToDriverProc DataSourceToDriver;
|
||||||
|
DriverToDataSourceProc DriverToDataSource;
|
||||||
char transact_status; /* Is a transaction is currently in progress */
|
char transact_status; /* Is a transaction is currently in progress */
|
||||||
char errormsg_created; /* has an informative error msg been created? */
|
char errormsg_created; /* has an informative error msg been created? */
|
||||||
};
|
};
|
||||||
@ -179,6 +227,7 @@ char CC_Destructor(ConnectionClass *self);
|
|||||||
int CC_cursor_count(ConnectionClass *self);
|
int CC_cursor_count(ConnectionClass *self);
|
||||||
char CC_cleanup(ConnectionClass *self);
|
char CC_cleanup(ConnectionClass *self);
|
||||||
char CC_abort(ConnectionClass *self);
|
char CC_abort(ConnectionClass *self);
|
||||||
|
int CC_set_translation (ConnectionClass *self);
|
||||||
char CC_connect(ConnectionClass *self, char do_password);
|
char CC_connect(ConnectionClass *self, char do_password);
|
||||||
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
|
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
|
||||||
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
|
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
|
||||||
@ -191,4 +240,5 @@ char CC_send_settings(ConnectionClass *self);
|
|||||||
void CC_lookup_lo(ConnectionClass *conn);
|
void CC_lookup_lo(ConnectionClass *conn);
|
||||||
void CC_log_error(char *func, char *desc, ConnectionClass *self);
|
void CC_log_error(char *func, char *desc, ConnectionClass *self);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,11 +16,23 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
@ -30,6 +42,16 @@
|
|||||||
#include "lobj.h"
|
#include "lobj.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#if !HAVE_STRICMP
|
||||||
|
#define stricmp(s1,s2) strcasecmp(s1,s2)
|
||||||
|
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
|
||||||
|
#endif
|
||||||
|
#ifndef SCHAR
|
||||||
|
typedef signed char SCHAR;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
/* How to map ODBC scalar functions {fn func(args)} to Postgres */
|
/* How to map ODBC scalar functions {fn func(args)} to Postgres */
|
||||||
@ -104,6 +126,15 @@ struct tm *tim;
|
|||||||
return COPY_OK;
|
return COPY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stmt->hdbc->DataSourceToDriver != NULL) {
|
||||||
|
int length = strlen (value);
|
||||||
|
stmt->hdbc->DataSourceToDriver (stmt->hdbc->translation_option,
|
||||||
|
SQL_CHAR,
|
||||||
|
value, length,
|
||||||
|
value, length, NULL,
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
First convert any specific postgres types into more
|
First convert any specific postgres types into more
|
||||||
useable data.
|
useable data.
|
||||||
@ -738,6 +769,15 @@ char in_quote = FALSE;
|
|||||||
// make sure new_statement is always null-terminated
|
// make sure new_statement is always null-terminated
|
||||||
new_statement[npos] = '\0';
|
new_statement[npos] = '\0';
|
||||||
|
|
||||||
|
if(stmt->hdbc->DriverToDataSource != NULL) {
|
||||||
|
int length = strlen (new_statement);
|
||||||
|
stmt->hdbc->DriverToDataSource (stmt->hdbc->translation_option,
|
||||||
|
SQL_CHAR,
|
||||||
|
new_statement, length,
|
||||||
|
new_statement, length, NULL,
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,6 +921,12 @@ char *p;
|
|||||||
|
|
||||||
for (i = 0; i < strlen(si) && out < max; i++) {
|
for (i = 0; i < strlen(si) && out < max; i++) {
|
||||||
if (si[i] == '\n') {
|
if (si[i] == '\n') {
|
||||||
|
/* Only add the carriage-return if needed */
|
||||||
|
if (i > 0 && si[i-1] == '\r') {
|
||||||
|
p[out++] = si[i];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
p[out++] = '\r';
|
p[out++] = '\r';
|
||||||
p[out++] = '\n';
|
p[out++] = '\n';
|
||||||
}
|
}
|
||||||
@ -945,6 +991,26 @@ int i, y=0;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
conv_from_hex(unsigned char *s)
|
||||||
|
{
|
||||||
|
int i, y=0, val;
|
||||||
|
|
||||||
|
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')
|
||||||
|
val = s[i] - 'A' + 10;
|
||||||
|
else
|
||||||
|
val = s[i] - '0';
|
||||||
|
|
||||||
|
y += val * (int) pow(16, 2-i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
// convert octal escapes to bytes
|
// convert octal escapes to bytes
|
||||||
int
|
int
|
||||||
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
|
convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax)
|
||||||
@ -1009,6 +1075,50 @@ int i, o=0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
encode(char *in, char *out)
|
||||||
|
{
|
||||||
|
unsigned int i, o = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(in); i++) {
|
||||||
|
if ( in[i] == '+') {
|
||||||
|
sprintf(&out[o], "%%2B");
|
||||||
|
o += 3;
|
||||||
|
}
|
||||||
|
else if ( isspace(in[i])) {
|
||||||
|
out[o++] = '+';
|
||||||
|
}
|
||||||
|
else if ( ! isalnum(in[i])) {
|
||||||
|
sprintf(&out[o], "%%%02x", in[i]);
|
||||||
|
o += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[o++] = in[i];
|
||||||
|
}
|
||||||
|
out[o++] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
decode(char *in, char *out)
|
||||||
|
{
|
||||||
|
unsigned int i, o = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(in); i++) {
|
||||||
|
if (in[i] == '+')
|
||||||
|
out[o++] = ' ';
|
||||||
|
else if (in[i] == '%') {
|
||||||
|
sprintf(&out[o++], "%c", conv_from_hex(&in[i]));
|
||||||
|
i+=2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[o++] = in[i];
|
||||||
|
}
|
||||||
|
out[o++] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 1. get oid (from 'value')
|
/* 1. get oid (from 'value')
|
||||||
2. open the large object
|
2. open the large object
|
||||||
3. read from the large object (handle multiple GetData)
|
3. read from the large object (handle multiple GetData)
|
||||||
|
@ -43,6 +43,8 @@ char *convert_special_chars(char *si, char *dst, int used);
|
|||||||
int convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax);
|
int convert_pgbinary_to_char(char *value, char *rgbValue, int cbValueMax);
|
||||||
int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax);
|
int convert_from_pgbinary(unsigned char *value, unsigned char *rgbValue, int cbValueMax);
|
||||||
int convert_to_pgbinary(unsigned char *in, char *out, int len);
|
int convert_to_pgbinary(unsigned char *in, char *out, int len);
|
||||||
|
void encode(char *in, char *out);
|
||||||
|
void decode(char *in, char *out);
|
||||||
int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
int convert_lo(StatementClass *stmt, void *value, Int2 fCType, PTR rgbValue,
|
||||||
SDWORD cbValueMax, SDWORD *pcbValue, char multiple);
|
SDWORD cbValueMax, SDWORD *pcbValue, char multiple);
|
||||||
|
|
||||||
|
@ -16,10 +16,27 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <string.h>
|
||||||
|
#include "gpps.h"
|
||||||
|
#define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f)
|
||||||
|
#define SQLWritePrivateProfileString(a,b,c,d) WritePrivateProfileString(a,b,c,d)
|
||||||
|
#if !HAVE_STRICMP
|
||||||
|
#define stricmp(s1,s2) strcasecmp(s1,s2)
|
||||||
|
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
|
#include "convert.h"
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
#ifndef UNIX /* best to find a #ifdef for WINDOWS */
|
||||||
void
|
void
|
||||||
SetDlgStuff(HWND hdlg, ConnInfo *ci)
|
SetDlgStuff(HWND hdlg, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
@ -81,7 +98,9 @@ int CALLBACK driver_optionsProc(HWND hdlg,
|
|||||||
CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, globals.text_as_longvarchar);
|
CheckDlgButton(hdlg, DRV_TEXT_LONGVARCHAR, globals.text_as_longvarchar);
|
||||||
CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, globals.unknowns_as_longvarchar);
|
CheckDlgButton(hdlg, DRV_UNKNOWNS_LONGVARCHAR, globals.unknowns_as_longvarchar);
|
||||||
CheckDlgButton(hdlg, DRV_BOOLS_CHAR, globals.bools_as_char);
|
CheckDlgButton(hdlg, DRV_BOOLS_CHAR, globals.bools_as_char);
|
||||||
|
|
||||||
|
CheckDlgButton(hdlg, DRV_PARSE, globals.parse);
|
||||||
|
|
||||||
SetDlgItemInt(hdlg, DRV_CACHE_SIZE, globals.fetch_max, FALSE);
|
SetDlgItemInt(hdlg, DRV_CACHE_SIZE, globals.fetch_max, FALSE);
|
||||||
SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, globals.max_varchar_size, FALSE);
|
SetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, globals.max_varchar_size, FALSE);
|
||||||
SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, globals.max_longvarchar_size, TRUE);
|
SetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, globals.max_longvarchar_size, TRUE);
|
||||||
@ -117,6 +136,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
|
|||||||
globals.unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR);
|
globals.unknowns_as_longvarchar = IsDlgButtonChecked(hdlg, DRV_UNKNOWNS_LONGVARCHAR);
|
||||||
globals.bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR);
|
globals.bools_as_char = IsDlgButtonChecked(hdlg, DRV_BOOLS_CHAR);
|
||||||
|
|
||||||
|
globals.parse = IsDlgButtonChecked(hdlg, DRV_PARSE);
|
||||||
|
|
||||||
globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
|
globals.fetch_max = GetDlgItemInt(hdlg, DRV_CACHE_SIZE, NULL, FALSE);
|
||||||
globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
|
globals.max_varchar_size = GetDlgItemInt(hdlg, DRV_VARCHAR_SIZE, NULL, FALSE);
|
||||||
globals.max_longvarchar_size= GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); // allows for SQL_NO_TOTAL
|
globals.max_longvarchar_size= GetDlgItemInt(hdlg, DRV_LONGVARCHAR_SIZE, NULL, TRUE); // allows for SQL_NO_TOTAL
|
||||||
@ -141,6 +162,8 @@ int CALLBACK driver_optionsProc(HWND hdlg,
|
|||||||
CheckDlgButton(hdlg, DRV_READONLY, DEFAULT_READONLY);
|
CheckDlgButton(hdlg, DRV_READONLY, DEFAULT_READONLY);
|
||||||
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, DEFAULT_USEDECLAREFETCH);
|
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, DEFAULT_USEDECLAREFETCH);
|
||||||
|
|
||||||
|
CheckDlgButton(hdlg, DRV_PARSE, DEFAULT_PARSE);
|
||||||
|
|
||||||
/* Unknown Sizes */
|
/* Unknown Sizes */
|
||||||
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
|
CheckDlgButton(hdlg, DRV_UNKNOWN_DONTKNOW, 0);
|
||||||
CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
|
CheckDlgButton(hdlg, DRV_UNKNOWN_LONGEST, 0);
|
||||||
@ -185,7 +208,6 @@ int CALLBACK ds_optionsProc(HWND hdlg,
|
|||||||
{
|
{
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
// int unknown_sizes;
|
|
||||||
|
|
||||||
switch (wMsg) {
|
switch (wMsg) {
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
@ -209,20 +231,6 @@ char buf[128];
|
|||||||
else
|
else
|
||||||
CheckDlgButton(hdlg, DS_PG62, 0);
|
CheckDlgButton(hdlg, DS_PG62, 0);
|
||||||
|
|
||||||
/* Unknown Data Type sizes -- currently only needed in Driver options.
|
|
||||||
switch (atoi(ci->unknown_sizes)) {
|
|
||||||
case UNKNOWNS_AS_DONTKNOW:
|
|
||||||
CheckDlgButton(hdlg, DS_UNKNOWN_DONTKNOW, 1);
|
|
||||||
break;
|
|
||||||
case UNKNOWNS_AS_LONGEST:
|
|
||||||
CheckDlgButton(hdlg, DS_UNKNOWN_LONGEST, 1);
|
|
||||||
break;
|
|
||||||
case UNKNOWNS_AS_MAX:
|
|
||||||
default:
|
|
||||||
CheckDlgButton(hdlg, DS_UNKNOWN_MAX, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
|
CheckDlgButton(hdlg, DS_SHOWOIDCOLUMN, atoi(ci->show_oid_column));
|
||||||
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
|
CheckDlgButton(hdlg, DS_FAKEOIDINDEX, atoi(ci->fake_oid_index));
|
||||||
@ -259,18 +267,6 @@ char buf[128];
|
|||||||
ci->protocol[0] = '\0';
|
ci->protocol[0] = '\0';
|
||||||
|
|
||||||
|
|
||||||
/* Unknown Data Type sizes -- currently only needed in Driver options.
|
|
||||||
if (IsDlgButtonChecked(hdlg, DS_UNKNOWN_MAX))
|
|
||||||
unknown_sizes = UNKNOWNS_AS_MAX;
|
|
||||||
else if (IsDlgButtonChecked(hdlg, DS_UNKNOWN_DONTKNOW))
|
|
||||||
unknown_sizes = UNKNOWNS_AS_DONTKNOW;
|
|
||||||
else if (IsDlgButtonChecked(hdlg, DS_UNKNOWN_LONGEST))
|
|
||||||
unknown_sizes = UNKNOWNS_AS_LONGEST;
|
|
||||||
else
|
|
||||||
unknown_sizes = UNKNOWNS_AS_MAX;
|
|
||||||
|
|
||||||
sprintf(ci->unknown_sizes, "%d", unknown_sizes);
|
|
||||||
*/
|
|
||||||
|
|
||||||
sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
|
sprintf(ci->show_system_tables, "%d", IsDlgButtonChecked(hdlg, DS_SHOWSYSTEMTABLES));
|
||||||
|
|
||||||
@ -295,27 +291,36 @@ char buf[128];
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* !UNIX */
|
||||||
|
|
||||||
void
|
void
|
||||||
makeConnectString(char *connect_string, ConnInfo *ci)
|
makeConnectString(char *connect_string, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
char got_dsn = (ci->dsn[0] != '\0');
|
char got_dsn = (ci->dsn[0] != '\0');
|
||||||
|
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
||||||
|
|
||||||
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;READONLY=%s;PWD=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s",
|
/* fundamental info */
|
||||||
|
sprintf(connect_string, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
|
||||||
got_dsn ? "DSN" : "DRIVER",
|
got_dsn ? "DSN" : "DRIVER",
|
||||||
got_dsn ? ci->dsn : ci->driver,
|
got_dsn ? ci->dsn : ci->driver,
|
||||||
ci->database,
|
ci->database,
|
||||||
ci->server,
|
ci->server,
|
||||||
ci->port,
|
ci->port,
|
||||||
ci->username,
|
ci->username,
|
||||||
|
ci->password);
|
||||||
|
|
||||||
|
encode(ci->conn_settings, encoded_conn_settings);
|
||||||
|
|
||||||
|
/* extra info */
|
||||||
|
sprintf(&connect_string[strlen(connect_string)],
|
||||||
|
";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s",
|
||||||
ci->readonly,
|
ci->readonly,
|
||||||
ci->password,
|
|
||||||
ci->protocol,
|
ci->protocol,
|
||||||
// ci->unknown_sizes, -- currently only needed in Driver options.
|
|
||||||
ci->fake_oid_index,
|
ci->fake_oid_index,
|
||||||
ci->show_oid_column,
|
ci->show_oid_column,
|
||||||
ci->row_versioning,
|
ci->row_versioning,
|
||||||
ci->show_system_tables,
|
ci->show_system_tables,
|
||||||
ci->conn_settings);
|
encoded_conn_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -349,10 +354,6 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
|||||||
else if (stricmp(attribute, INI_PROTOCOL) == 0)
|
else if (stricmp(attribute, INI_PROTOCOL) == 0)
|
||||||
strcpy(ci->protocol, value);
|
strcpy(ci->protocol, value);
|
||||||
|
|
||||||
/*
|
|
||||||
else if (stricmp(attribute, INI_UNKNOWNSIZES) == 0)
|
|
||||||
strcpy(ci->unknown_sizes, value);
|
|
||||||
*/
|
|
||||||
else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0)
|
else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0)
|
||||||
strcpy(ci->show_oid_column, value);
|
strcpy(ci->show_oid_column, value);
|
||||||
|
|
||||||
@ -365,9 +366,10 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
|||||||
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
|
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0)
|
||||||
strcpy(ci->show_system_tables, value);
|
strcpy(ci->show_system_tables, value);
|
||||||
|
|
||||||
else if (stricmp(attribute, INI_CONNSETTINGS) == 0)
|
else if (stricmp(attribute, INI_CONNSETTINGS) == 0) {
|
||||||
strcpy(ci->conn_settings, value);
|
decode(value, ci->conn_settings);
|
||||||
|
// strcpy(ci->conn_settings, value);
|
||||||
|
}
|
||||||
|
|
||||||
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',readonly='%s',protocol='%s', conn_settings='%s')\n",
|
mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',readonly='%s',protocol='%s', conn_settings='%s')\n",
|
||||||
ci->dsn,
|
ci->dsn,
|
||||||
@ -378,7 +380,6 @@ copyAttributes(ConnInfo *ci, char *attribute, char *value)
|
|||||||
ci->port,
|
ci->port,
|
||||||
ci->readonly,
|
ci->readonly,
|
||||||
ci->protocol,
|
ci->protocol,
|
||||||
// ci->unknown_sizes,
|
|
||||||
ci->conn_settings);
|
ci->conn_settings);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -392,10 +393,6 @@ getDSNdefaults(ConnInfo *ci)
|
|||||||
if (ci->readonly[0] == '\0')
|
if (ci->readonly[0] == '\0')
|
||||||
sprintf(ci->readonly, "%d", globals.readonly);
|
sprintf(ci->readonly, "%d", globals.readonly);
|
||||||
|
|
||||||
/* -- currently only needed in Driver options.
|
|
||||||
if (ci->unknown_sizes[0] == '\0')
|
|
||||||
sprintf(ci->unknown_sizes, "%d", globals.unknown_sizes);
|
|
||||||
*/
|
|
||||||
if (ci->fake_oid_index[0] == '\0')
|
if (ci->fake_oid_index[0] == '\0')
|
||||||
sprintf(ci->fake_oid_index, "%d", DEFAULT_FAKEOIDINDEX);
|
sprintf(ci->fake_oid_index, "%d", DEFAULT_FAKEOIDINDEX);
|
||||||
|
|
||||||
@ -414,6 +411,7 @@ void
|
|||||||
getDSNinfo(ConnInfo *ci, char overwrite)
|
getDSNinfo(ConnInfo *ci, char overwrite)
|
||||||
{
|
{
|
||||||
char *DSN = ci->dsn;
|
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 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 is null and no driver, then use the default datasource.
|
||||||
@ -447,10 +445,6 @@ char *DSN = ci->dsn;
|
|||||||
if ( ci->readonly[0] == '\0' || overwrite)
|
if ( ci->readonly[0] == '\0' || overwrite)
|
||||||
SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->readonly, sizeof(ci->readonly), ODBC_INI);
|
SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->readonly, sizeof(ci->readonly), ODBC_INI);
|
||||||
|
|
||||||
/* -- currently only needed in Driver options.
|
|
||||||
if ( ci->unknown_sizes[0] == '\0' || overwrite)
|
|
||||||
SQLGetPrivateProfileString(DSN, INI_UNKNOWNSIZES, "", ci->unknown_sizes, sizeof(ci->unknown_sizes), ODBC_INI);
|
|
||||||
*/
|
|
||||||
if ( ci->show_oid_column[0] == '\0' || overwrite)
|
if ( ci->show_oid_column[0] == '\0' || overwrite)
|
||||||
SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, "", ci->show_oid_column, sizeof(ci->show_oid_column), ODBC_INI);
|
SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, "", ci->show_oid_column, sizeof(ci->show_oid_column), ODBC_INI);
|
||||||
|
|
||||||
@ -466,8 +460,16 @@ char *DSN = ci->dsn;
|
|||||||
if ( ci->protocol[0] == '\0' || overwrite)
|
if ( ci->protocol[0] == '\0' || overwrite)
|
||||||
SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI);
|
SQLGetPrivateProfileString(DSN, INI_PROTOCOL, "", ci->protocol, sizeof(ci->protocol), ODBC_INI);
|
||||||
|
|
||||||
if ( ci->conn_settings[0] == '\0' || overwrite)
|
if ( ci->conn_settings[0] == '\0' || overwrite) {
|
||||||
SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", ci->conn_settings, sizeof(ci->conn_settings), ODBC_INI);
|
SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, "", encoded_conn_settings, sizeof(encoded_conn_settings), ODBC_INI);
|
||||||
|
decode(encoded_conn_settings, ci->conn_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ci->translation_dll[0] == '\0' || overwrite)
|
||||||
|
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONDLL, "", ci->translation_dll, sizeof(ci->translation_dll), ODBC_INI);
|
||||||
|
|
||||||
|
if ( ci->translation_option[0] == '\0' || overwrite)
|
||||||
|
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
|
||||||
|
|
||||||
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
|
qlog("DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
|
||||||
DSN,
|
DSN,
|
||||||
@ -481,10 +483,13 @@ char *DSN = ci->dsn;
|
|||||||
ci->protocol,
|
ci->protocol,
|
||||||
ci->show_oid_column,
|
ci->show_oid_column,
|
||||||
ci->fake_oid_index,
|
ci->fake_oid_index,
|
||||||
// ci->unknown_sizes,
|
|
||||||
ci->show_system_tables);
|
ci->show_system_tables);
|
||||||
qlog(" conn_settings='%s'\n",
|
qlog(" conn_settings='%s'\n",
|
||||||
ci->conn_settings);
|
ci->conn_settings);
|
||||||
|
qlog(" translation_dll='%s',translation_option='%s'\n",
|
||||||
|
ci->translation_dll,
|
||||||
|
ci->translation_option);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -493,6 +498,9 @@ void
|
|||||||
writeDSNinfo(ConnInfo *ci)
|
writeDSNinfo(ConnInfo *ci)
|
||||||
{
|
{
|
||||||
char *DSN = ci->dsn;
|
char *DSN = ci->dsn;
|
||||||
|
char encoded_conn_settings[LARGE_REGISTRY_LEN];
|
||||||
|
|
||||||
|
encode(ci->conn_settings, encoded_conn_settings);
|
||||||
|
|
||||||
SQLWritePrivateProfileString(DSN,
|
SQLWritePrivateProfileString(DSN,
|
||||||
INI_KDESC,
|
INI_KDESC,
|
||||||
@ -529,12 +537,6 @@ char *DSN = ci->dsn;
|
|||||||
ci->readonly,
|
ci->readonly,
|
||||||
ODBC_INI);
|
ODBC_INI);
|
||||||
|
|
||||||
/* -- currently only needed in Driver options.
|
|
||||||
SQLWritePrivateProfileString(DSN,
|
|
||||||
INI_UNKNOWNSIZES,
|
|
||||||
ci->unknown_sizes,
|
|
||||||
ODBC_INI);
|
|
||||||
*/
|
|
||||||
SQLWritePrivateProfileString(DSN,
|
SQLWritePrivateProfileString(DSN,
|
||||||
INI_SHOWOIDCOLUMN,
|
INI_SHOWOIDCOLUMN,
|
||||||
ci->show_oid_column,
|
ci->show_oid_column,
|
||||||
@ -562,7 +564,7 @@ char *DSN = ci->dsn;
|
|||||||
|
|
||||||
SQLWritePrivateProfileString(DSN,
|
SQLWritePrivateProfileString(DSN,
|
||||||
INI_CONNSETTINGS,
|
INI_CONNSETTINGS,
|
||||||
ci->conn_settings,
|
encoded_conn_settings,
|
||||||
ODBC_INI);
|
ODBC_INI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +633,7 @@ char temp[128];
|
|||||||
globals.unique_index = atoi(temp);
|
globals.unique_index = atoi(temp);
|
||||||
|
|
||||||
|
|
||||||
// Unknown Sizes is stored in the driver section AND per datasource
|
// Unknown Sizes is stored in the driver section only
|
||||||
SQLGetPrivateProfileString(DBMS_NAME, INI_UNKNOWNSIZES, "",
|
SQLGetPrivateProfileString(DBMS_NAME, INI_UNKNOWNSIZES, "",
|
||||||
temp, sizeof(temp), ODBCINST_INI);
|
temp, sizeof(temp), ODBCINST_INI);
|
||||||
if ( temp[0] == '\0')
|
if ( temp[0] == '\0')
|
||||||
@ -648,6 +650,13 @@ char temp[128];
|
|||||||
else
|
else
|
||||||
globals.lie = atoi(temp);
|
globals.lie = atoi(temp);
|
||||||
|
|
||||||
|
// Parse statements
|
||||||
|
SQLGetPrivateProfileString(DBMS_NAME, INI_PARSE, "",
|
||||||
|
temp, sizeof(temp), ODBCINST_INI);
|
||||||
|
if ( temp[0] == '\0')
|
||||||
|
globals.parse = DEFAULT_PARSE;
|
||||||
|
else
|
||||||
|
globals.parse = atoi(temp);
|
||||||
|
|
||||||
// Readonly is stored in the driver section AND per datasource
|
// Readonly is stored in the driver section AND per datasource
|
||||||
SQLGetPrivateProfileString(DBMS_NAME, INI_READONLY, "",
|
SQLGetPrivateProfileString(DBMS_NAME, INI_READONLY, "",
|
||||||
@ -772,6 +781,10 @@ char tmp[128];
|
|||||||
SQLWritePrivateProfileString(DBMS_NAME,
|
SQLWritePrivateProfileString(DBMS_NAME,
|
||||||
INI_BOOLSASCHAR, tmp, ODBCINST_INI);
|
INI_BOOLSASCHAR, tmp, ODBCINST_INI);
|
||||||
|
|
||||||
|
sprintf(tmp, "%d", globals.parse);
|
||||||
|
SQLWritePrivateProfileString(DBMS_NAME,
|
||||||
|
INI_PARSE, tmp, ODBCINST_INI);
|
||||||
|
|
||||||
sprintf(tmp, "%d", globals.max_varchar_size);
|
sprintf(tmp, "%d", globals.max_varchar_size);
|
||||||
SQLWritePrivateProfileString(DBMS_NAME,
|
SQLWritePrivateProfileString(DBMS_NAME,
|
||||||
INI_MAXVARCHARSIZE, tmp, ODBCINST_INI);
|
INI_MAXVARCHARSIZE, tmp, ODBCINST_INI);
|
||||||
|
@ -10,12 +10,19 @@
|
|||||||
#ifndef __DLG_SPECIFIC_H__
|
#ifndef __DLG_SPECIFIC_H__
|
||||||
#define __DLG_SPECIFIC_H__
|
#define __DLG_SPECIFIC_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#ifndef UNIX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Unknown data type sizes */
|
/* Unknown data type sizes */
|
||||||
#define UNKNOWNS_AS_MAX 0
|
#define UNKNOWNS_AS_MAX 0
|
||||||
@ -23,8 +30,13 @@
|
|||||||
#define UNKNOWNS_AS_LONGEST 2
|
#define UNKNOWNS_AS_LONGEST 2
|
||||||
|
|
||||||
/* INI File Stuff */
|
/* INI File Stuff */
|
||||||
#define ODBC_INI "ODBC.INI" /* ODBC initialization file */
|
#ifdef UNIX
|
||||||
#define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
|
#define ODBC_INI ".odbc.ini"
|
||||||
|
#define ODBCINST_INI "/etc/odbcinst.ini"
|
||||||
|
#else
|
||||||
|
#define ODBC_INI "ODBC.INI" /* ODBC initialization file */
|
||||||
|
#define ODBCINST_INI "ODBCINST.INI" /* ODBC Installation file */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */
|
#define INI_DSN DBMS_NAME /* Name of default Datasource in ini file (not used?) */
|
||||||
#define INI_KDESC "Description" /* Data source description */
|
#define INI_KDESC "Description" /* Data source description */
|
||||||
@ -58,8 +70,14 @@
|
|||||||
#define INI_ROWVERSIONING "RowVersioning"
|
#define INI_ROWVERSIONING "RowVersioning"
|
||||||
#define INI_SHOWSYSTEMTABLES "ShowSystemTables"
|
#define INI_SHOWSYSTEMTABLES "ShowSystemTables"
|
||||||
#define INI_LIE "Lie"
|
#define INI_LIE "Lie"
|
||||||
|
#define INI_PARSE "Parse"
|
||||||
#define INI_EXTRASYSTABLEPREFIXES "ExtraSysTablePrefixes"
|
#define INI_EXTRASYSTABLEPREFIXES "ExtraSysTablePrefixes"
|
||||||
|
|
||||||
|
#define INI_TRANSLATIONNAME "TranslationName"
|
||||||
|
#define INI_TRANSLATIONDLL "TranslationDLL"
|
||||||
|
#define INI_TRANSLATIONOPTION "TranslationOption"
|
||||||
|
|
||||||
|
|
||||||
/* Connection Defaults */
|
/* Connection Defaults */
|
||||||
#define DEFAULT_PORT "5432"
|
#define DEFAULT_PORT "5432"
|
||||||
#define DEFAULT_READONLY 1
|
#define DEFAULT_READONLY 1
|
||||||
@ -78,13 +96,14 @@
|
|||||||
#define DEFAULT_ROWVERSIONING 0
|
#define DEFAULT_ROWVERSIONING 0
|
||||||
#define DEFAULT_SHOWSYSTEMTABLES 0 // dont show system tables
|
#define DEFAULT_SHOWSYSTEMTABLES 0 // dont show system tables
|
||||||
#define DEFAULT_LIE 0
|
#define DEFAULT_LIE 0
|
||||||
|
#define DEFAULT_PARSE 0
|
||||||
|
|
||||||
#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;"
|
#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;"
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
void updateGlobals(void);
|
|
||||||
void getGlobalDefaults(void);
|
void getGlobalDefaults(void);
|
||||||
|
|
||||||
|
#ifndef UNIX
|
||||||
void SetDlgStuff(HWND hdlg, ConnInfo *ci);
|
void SetDlgStuff(HWND hdlg, ConnInfo *ci);
|
||||||
void GetDlgStuff(HWND hdlg, ConnInfo *ci);
|
void GetDlgStuff(HWND hdlg, ConnInfo *ci);
|
||||||
|
|
||||||
@ -96,12 +115,14 @@ int CALLBACK ds_optionsProc(HWND hdlg,
|
|||||||
WORD wMsg,
|
WORD wMsg,
|
||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
LPARAM lParam);
|
LPARAM lParam);
|
||||||
|
#endif /* ! UNIX */
|
||||||
|
|
||||||
|
void updateGlobals(void);
|
||||||
|
void writeDSNinfo(ConnInfo *ci);
|
||||||
|
void getDSNdefaults(ConnInfo *ci);
|
||||||
|
void getDSNinfo(ConnInfo *ci, char overwrite);
|
||||||
void makeConnectString(char *connect_string, ConnInfo *ci);
|
void makeConnectString(char *connect_string, ConnInfo *ci);
|
||||||
void copyAttributes(ConnInfo *ci, char *attribute, char *value);
|
void copyAttributes(ConnInfo *ci, char *attribute, char *value);
|
||||||
void getDSNdefaults(ConnInfo *ci);
|
|
||||||
|
|
||||||
void getDSNinfo(ConnInfo *ci, char overwrite);
|
|
||||||
void writeDSNinfo(ConnInfo *ci);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,28 +12,56 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#define NEAR
|
||||||
|
#else
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#define stricmp(s1,s2) strcasecmp(s1,s2)
|
||||||
|
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (BOOL)1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (BOOL)0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
|
|
||||||
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
|
|
||||||
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);
|
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);
|
||||||
|
|
||||||
|
#ifndef UNIX /* should be something like ifdef WINDOWS */
|
||||||
|
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
|
||||||
|
|
||||||
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
|
extern HINSTANCE NEAR s_hModule; /* Saved module handle. */
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
|
||||||
@ -51,23 +79,25 @@ char *func = "SQLDriverConnect";
|
|||||||
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
RETCODE dialog_result;
|
RETCODE dialog_result;
|
||||||
char connect_string[MAX_CONNECT_STRING];
|
char connStrIn[MAX_CONNECT_STRING];
|
||||||
|
char connStrOut[MAX_CONNECT_STRING];
|
||||||
int retval;
|
int retval;
|
||||||
char password_required = FALSE;
|
char password_required = FALSE;
|
||||||
|
|
||||||
mylog("**** SQLDriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, szConnStrIn);
|
|
||||||
|
|
||||||
if ( ! conn) {
|
if ( ! conn) {
|
||||||
CC_log_error(func, "", NULL);
|
CC_log_error(func, "", NULL);
|
||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
qlog("conn=%u, SQLDriverConnect( in)='%s'\n", conn, szConnStrIn);
|
make_string(szConnStrIn, cbConnStrIn, connStrIn);
|
||||||
|
|
||||||
|
mylog("**** SQLDriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
|
||||||
|
qlog("conn=%u, SQLDriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);
|
||||||
|
|
||||||
ci = &(conn->connInfo);
|
ci = &(conn->connInfo);
|
||||||
|
|
||||||
// Parse the connect string and fill in conninfo for this hdbc.
|
// Parse the connect string and fill in conninfo for this hdbc.
|
||||||
dconn_get_connect_attributes(szConnStrIn, ci);
|
dconn_get_connect_attributes(connStrIn, ci);
|
||||||
|
|
||||||
// If the ConnInfo in the hdbc is missing anything,
|
// If the ConnInfo in the hdbc is missing anything,
|
||||||
// this function will fill them in from the registry (assuming
|
// this function will fill them in from the registry (assuming
|
||||||
@ -81,6 +111,7 @@ dialog:
|
|||||||
ci->focus_password = password_required;
|
ci->focus_password = password_required;
|
||||||
|
|
||||||
switch(fDriverCompletion) {
|
switch(fDriverCompletion) {
|
||||||
|
#ifndef UNIX /* again should be ifdef WINDOWS like */
|
||||||
case SQL_DRIVER_PROMPT:
|
case SQL_DRIVER_PROMPT:
|
||||||
dialog_result = dconn_DoDialog(hwnd, ci);
|
dialog_result = dconn_DoDialog(hwnd, ci);
|
||||||
if(dialog_result != SQL_SUCCESS) {
|
if(dialog_result != SQL_SUCCESS) {
|
||||||
@ -88,9 +119,13 @@ dialog:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_DRIVER_COMPLETE:
|
|
||||||
case SQL_DRIVER_COMPLETE_REQUIRED:
|
case SQL_DRIVER_COMPLETE_REQUIRED:
|
||||||
/* Password is not a required parameter. */
|
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
|
case SQL_DRIVER_COMPLETE:
|
||||||
|
|
||||||
|
/* Password is not a required parameter. */
|
||||||
if( ci->username[0] == '\0' ||
|
if( ci->username[0] == '\0' ||
|
||||||
ci->server[0] == '\0' ||
|
ci->server[0] == '\0' ||
|
||||||
ci->database[0] == '\0' ||
|
ci->database[0] == '\0' ||
|
||||||
@ -103,6 +138,11 @@ dialog:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#else
|
||||||
|
case SQL_DRIVER_PROMPT:
|
||||||
|
case SQL_DRIVER_COMPLETE:
|
||||||
|
case SQL_DRIVER_COMPLETE_REQUIRED:
|
||||||
|
#endif
|
||||||
case SQL_DRIVER_NOPROMPT:
|
case SQL_DRIVER_NOPROMPT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -122,14 +162,16 @@ dialog:
|
|||||||
|
|
||||||
if(szConnStrOut) {
|
if(szConnStrOut) {
|
||||||
|
|
||||||
// return the completed string to the caller.
|
/* Return the completed string to the caller.
|
||||||
|
Only construct the connect string if a dialog was put up,
|
||||||
makeConnectString(connect_string, ci);
|
otherwise, just copy the connection input string to the output.
|
||||||
|
*/
|
||||||
|
makeConnectString(connStrOut, ci);
|
||||||
|
|
||||||
if(pcbConnStrOut) {
|
if(pcbConnStrOut) {
|
||||||
*pcbConnStrOut = strlen(connect_string);
|
*pcbConnStrOut = strlen(connStrOut);
|
||||||
}
|
}
|
||||||
strncpy_null(szConnStrOut, connect_string, cbConnStrOutMax);
|
strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("szConnStrOut = '%s'\n", szConnStrOut);
|
mylog("szConnStrOut = '%s'\n", szConnStrOut);
|
||||||
@ -143,8 +185,12 @@ dialog:
|
|||||||
return SQL_ERROR; /* need a password but not allowed to prompt so error */
|
return SQL_ERROR; /* need a password but not allowed to prompt so error */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#ifndef UNIX
|
||||||
password_required = TRUE;
|
password_required = TRUE;
|
||||||
goto dialog;
|
goto dialog;
|
||||||
|
#else
|
||||||
|
return SQL_ERROR; /* until a better solution is found. */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (retval == 0) {
|
else if (retval == 0) {
|
||||||
@ -157,7 +203,7 @@ dialog:
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef UNIX /* yet another candidate for ifdef WINDOWS */
|
||||||
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci)
|
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
int dialog_result;
|
int dialog_result;
|
||||||
@ -216,6 +262,7 @@ ConnInfo *ci;
|
|||||||
else if (ci->focus_password)
|
else if (ci->focus_password)
|
||||||
SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
|
SetFocus(GetDlgItem(hdlg, IDC_PASSWORD));
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
@ -252,7 +299,7 @@ ConnInfo *ci;
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! UNIX */
|
||||||
|
|
||||||
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
|
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
|
||||||
{
|
{
|
||||||
|
@ -10,10 +10,21 @@
|
|||||||
#ifndef __ENVIRON_H__
|
#ifndef __ENVIRON_H__
|
||||||
#define __ENVIRON_H__
|
#define __ENVIRON_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ENV_ALLOC_ERROR 1
|
#define ENV_ALLOC_ERROR 1
|
||||||
|
|
||||||
|
@ -13,11 +13,21 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
@ -27,6 +37,15 @@
|
|||||||
#include "lobj.h"
|
#include "lobj.h"
|
||||||
|
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLExecDirect(
|
||||||
|
HSTMT hstmt,
|
||||||
|
UCHAR FAR *szSqlStr,
|
||||||
|
SDWORD cbSqlStr)
|
||||||
|
{
|
||||||
|
return _SQLExecDirect(hstmt, szSqlStr, cbSqlStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Perform a Prepare on the SQL statement
|
// Perform a Prepare on the SQL statement
|
||||||
RETCODE SQL_API SQLPrepare(HSTMT hstmt,
|
RETCODE SQL_API SQLPrepare(HSTMT hstmt,
|
||||||
UCHAR FAR *szSqlStr,
|
UCHAR FAR *szSqlStr,
|
||||||
@ -111,7 +130,7 @@ StatementClass *self = (StatementClass *) hstmt;
|
|||||||
|
|
||||||
// Performs the equivalent of SQLPrepare, followed by SQLExecute.
|
// Performs the equivalent of SQLPrepare, followed by SQLExecute.
|
||||||
|
|
||||||
RETCODE SQL_API SQLExecDirect(
|
RETCODE SQL_API _SQLExecDirect(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
UCHAR FAR *szSqlStr,
|
UCHAR FAR *szSqlStr,
|
||||||
SDWORD cbSqlStr)
|
SDWORD cbSqlStr)
|
||||||
@ -359,6 +378,8 @@ StatementClass *stmt = (StatementClass *) hstmt;
|
|||||||
stmt->current_exec_param = -1;
|
stmt->current_exec_param = -1;
|
||||||
stmt->put_data = FALSE;
|
stmt->put_data = FALSE;
|
||||||
|
|
||||||
|
return SQL_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - -
|
// - - - - - - - - -
|
||||||
|
475
src/interfaces/odbc/gpps.c
Normal file
475
src/interfaces/odbc/gpps.c
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
// GetPrivateProfileString() -- approximate implementation of
|
||||||
|
// Windows NT System Services version of GetPrivateProfileString()
|
||||||
|
// probably doesn't handle the NULL key for section name or value key
|
||||||
|
// correctly also, doesn't provide Microsoft backwards compatability
|
||||||
|
// wrt TAB characters in the value string -- Microsoft terminates value
|
||||||
|
// at the first TAB, but I couldn't discover what the behavior should
|
||||||
|
// be regarding TABS in quoted strings so, I treat tabs like any other
|
||||||
|
// characters -- NO comments following value string separated by a TAB
|
||||||
|
// are allowed (that is an anachronism anyway)
|
||||||
|
// Added code to search for ODBC_INI file in users home directory on
|
||||||
|
// Unix
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h> // produced by configure
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if HAVE_PWD_H
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "gpps.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE ((BOOL)1)
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE ((BOOL)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#else
|
||||||
|
#define MAXPATHLEN 255
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
GetPrivateProfileString(char *theSection, // section name
|
||||||
|
char *theKey, // search key name
|
||||||
|
char *theDefault, // default value if not found
|
||||||
|
char *theReturnBuffer, // return value stored here
|
||||||
|
size_t theReturnBufferLength, // byte length of return buffer
|
||||||
|
char *theIniFileName) // pathname of ini file to search
|
||||||
|
{
|
||||||
|
char buf[MAXPATHLEN+1];
|
||||||
|
char* ptr = 0;
|
||||||
|
FILE* aFile = 0;
|
||||||
|
size_t aLength;
|
||||||
|
char aLine[2048];
|
||||||
|
char *aValue;
|
||||||
|
char *aString;
|
||||||
|
size_t aLineLength;
|
||||||
|
size_t aReturnLength = 0;
|
||||||
|
|
||||||
|
BOOL aSectionFound = FALSE;
|
||||||
|
BOOL aKeyFound = FALSE;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
j = strlen(theIniFileName) + 1;
|
||||||
|
ptr = (char*)getpwuid(getuid()); // get user info
|
||||||
|
|
||||||
|
if( ptr == NULL)
|
||||||
|
{
|
||||||
|
if( MAXPATHLEN < j )
|
||||||
|
theIniFileName[MAXPATHLEN] = '\0';
|
||||||
|
|
||||||
|
sprintf(buf,"%s",theIniFileName);
|
||||||
|
}
|
||||||
|
ptr = ((struct passwd*)ptr)->pw_dir; // get user home dir
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
if( MAXPATHLEN < strlen(ptr) + j )
|
||||||
|
{
|
||||||
|
if( MAXPATHLEN < strlen(ptr) )
|
||||||
|
ptr[MAXPATHLEN] = '\0';
|
||||||
|
else
|
||||||
|
theIniFileName[MAXPATHLEN-strlen(ptr)] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
aFile = (FILE*)(buf ? fopen(buf, "r") : NULL);
|
||||||
|
if(!aFile) {
|
||||||
|
sprintf(buf,"%s",theIniFileName);
|
||||||
|
aFile = (FILE*)(buf ? fopen(buf, "r") : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aLength = (theDefault == NULL) ? 0 : strlen(theDefault);
|
||||||
|
|
||||||
|
if(theReturnBufferLength == 0 || theReturnBuffer == NULL)
|
||||||
|
{
|
||||||
|
if(aFile)
|
||||||
|
{
|
||||||
|
fclose(aFile);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(aFile == NULL)
|
||||||
|
{
|
||||||
|
// no ini file specified, return the default
|
||||||
|
|
||||||
|
++aLength; // room for NULL char
|
||||||
|
aLength = theReturnBufferLength < aLength ?
|
||||||
|
theReturnBufferLength : aLength;
|
||||||
|
strncpy(theReturnBuffer, theDefault, aLength);
|
||||||
|
theReturnBuffer[aLength - 1] = '\0';
|
||||||
|
return aLength - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while(fgets(aLine, sizeof(aLine), aFile) != NULL)
|
||||||
|
{
|
||||||
|
aLineLength = strlen(aLine);
|
||||||
|
// strip final '\n'
|
||||||
|
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n')
|
||||||
|
{
|
||||||
|
aLine[aLineLength - 1] = '\0';
|
||||||
|
}
|
||||||
|
switch(*aLine)
|
||||||
|
{
|
||||||
|
case ' ': // blank line
|
||||||
|
case ';': // comment line
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[': // section marker
|
||||||
|
|
||||||
|
if( (aString = strchr(aLine, ']')) )
|
||||||
|
{
|
||||||
|
*aString = '\0';
|
||||||
|
|
||||||
|
// accept as matched if NULL key or exact match
|
||||||
|
|
||||||
|
if(!theSection || !strcmp(aLine + 1, theSection))
|
||||||
|
{
|
||||||
|
aSectionFound = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
aValue = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aValue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// strip trailing blanks from key
|
||||||
|
|
||||||
|
if(aString)
|
||||||
|
{
|
||||||
|
while(--aString >= aLine && *aString == ' ')
|
||||||
|
{
|
||||||
|
*aString = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if key is matched
|
||||||
|
|
||||||
|
if(theKey == NULL || !strcmp(theKey, aLine))
|
||||||
|
{
|
||||||
|
// 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 == ' ')
|
||||||
|
{
|
||||||
|
*aString = '\0';
|
||||||
|
--aLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unquote value if quoted
|
||||||
|
|
||||||
|
if(aLength >= 2 && aValue[0] == '"' &&
|
||||||
|
aValue[aLength - 1] == '"')
|
||||||
|
{
|
||||||
|
// string quoted with double quotes
|
||||||
|
|
||||||
|
aValue[aLength - 1] = '\0';
|
||||||
|
++aValue;
|
||||||
|
aLength -= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// single quotes allowed also...
|
||||||
|
|
||||||
|
if(aLength >= 2 && aValue[0] == '\'' &&
|
||||||
|
aValue[aLength - 1] == '\'')
|
||||||
|
{
|
||||||
|
aValue[aLength - 1] = '\0';
|
||||||
|
++aValue;
|
||||||
|
aLength -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute maximum length copyable
|
||||||
|
|
||||||
|
aLineLength = (aLength <
|
||||||
|
theReturnBufferLength - aReturnLength) ? aLength :
|
||||||
|
theReturnBufferLength - aReturnLength;
|
||||||
|
|
||||||
|
// do the copy to return buffer
|
||||||
|
|
||||||
|
if(aLineLength)
|
||||||
|
{
|
||||||
|
strncpy(&theReturnBuffer[aReturnLength],
|
||||||
|
aValue, aLineLength);
|
||||||
|
aReturnLength += aLineLength;
|
||||||
|
if(aReturnLength < theReturnBufferLength)
|
||||||
|
{
|
||||||
|
theReturnBuffer[aReturnLength] = '\0';
|
||||||
|
++aReturnLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(aFile)
|
||||||
|
{
|
||||||
|
fclose(aFile);
|
||||||
|
aFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(aFile)
|
||||||
|
{
|
||||||
|
fclose(aFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!aKeyFound) { // key wasn't found return default
|
||||||
|
++aLength; // room for NULL char
|
||||||
|
aLength = theReturnBufferLength < aLength ?
|
||||||
|
theReturnBufferLength : aLength;
|
||||||
|
strncpy(theReturnBuffer, theDefault, aLength);
|
||||||
|
theReturnBuffer[aLength - 1] = '\0';
|
||||||
|
aReturnLength = aLength - 1;
|
||||||
|
}
|
||||||
|
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WritePrivateProfileString(char *theSection, // section name
|
||||||
|
char *theKey, // write key name
|
||||||
|
char *theBuffer, // input buffer
|
||||||
|
char *theIniFileName) // pathname of ini file to write
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 *theBuffer, // input buffer
|
||||||
|
char *theIniFileName) // pathname of ini file to write
|
||||||
|
{
|
||||||
|
char buf[MAXPATHLEN+1];
|
||||||
|
char* ptr = 0;
|
||||||
|
FILE* aFile = 0;
|
||||||
|
size_t aLength;
|
||||||
|
char aLine[2048];
|
||||||
|
char *aValue;
|
||||||
|
char *aString;
|
||||||
|
size_t aLineLength;
|
||||||
|
size_t aReturnLength = 0;
|
||||||
|
|
||||||
|
BOOL aSectionFound = FALSE;
|
||||||
|
BOOL keyFound = FALSE;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
// If this isn't correct processing we'll change it later
|
||||||
|
if(theSection == NULL || theKey == NULL || theBuffer == NULL ||
|
||||||
|
theIniFileName == NULL) return 0;
|
||||||
|
|
||||||
|
aLength = strlen(theBuffer);
|
||||||
|
if(aLength == 0) return 0;
|
||||||
|
|
||||||
|
j = strlen(theIniFileName) + 1;
|
||||||
|
ptr = (char*)getpwuid(getuid()); // get user info
|
||||||
|
|
||||||
|
if( ptr == NULL)
|
||||||
|
{
|
||||||
|
if( MAXPATHLEN < j )
|
||||||
|
theIniFileName[MAXPATHLEN] = '\0';
|
||||||
|
|
||||||
|
sprintf(buf,"%s",theIniFileName);
|
||||||
|
}
|
||||||
|
ptr = ((struct passwd*)ptr)->pw_dir; // get user home dir
|
||||||
|
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.
|
||||||
|
//
|
||||||
|
if( MAXPATHLEN < strlen(ptr) + j )
|
||||||
|
{
|
||||||
|
if( MAXPATHLEN < strlen(ptr) )
|
||||||
|
ptr[MAXPATHLEN] = '\0';
|
||||||
|
else
|
||||||
|
theIniFileName[MAXPATHLEN-strlen(ptr)] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
//
|
||||||
|
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL);
|
||||||
|
if(!aFile) {
|
||||||
|
sprintf(buf,"%s",theIniFileName);
|
||||||
|
aFile = (FILE*)(buf ? fopen(buf, "r+") : NULL);
|
||||||
|
if(!aFile) 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.
|
||||||
|
//
|
||||||
|
while(fgets(aLine, sizeof(aLine), aFile) != NULL)
|
||||||
|
{
|
||||||
|
aLineLength = strlen(aLine);
|
||||||
|
// strip final '\n'
|
||||||
|
if(aLineLength > 0 && aLine[aLineLength - 1] == '\n')
|
||||||
|
{
|
||||||
|
aLine[aLineLength - 1] = '\0';
|
||||||
|
}
|
||||||
|
switch(*aLine)
|
||||||
|
{
|
||||||
|
case ' ': // blank line
|
||||||
|
case ';': // comment line
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[': // section marker
|
||||||
|
|
||||||
|
if( (aString = strchr(aLine, ']')) )
|
||||||
|
{
|
||||||
|
*aString = '\0';
|
||||||
|
|
||||||
|
// accept as matched if key exact match
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
aValue = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aValue = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// strip trailing blanks from key
|
||||||
|
|
||||||
|
if(aString)
|
||||||
|
{
|
||||||
|
while(--aString >= aLine && *aString == ' ')
|
||||||
|
{
|
||||||
|
*aString = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if key is matched
|
||||||
|
|
||||||
|
if(!strcmp(theKey, aLine))
|
||||||
|
{
|
||||||
|
keyFound = TRUE;
|
||||||
|
// matched -- first, terminate value part
|
||||||
|
|
||||||
|
// overwrite current value
|
||||||
|
fseek(aFile,-aLineLength,SEEK_CUR);
|
||||||
|
// overwrite key and value
|
||||||
|
sprintf(aLine,"%s = %s\n",theKey,theBuffer);
|
||||||
|
fputs(aLine,aFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!keyFound) { // theKey wasn't in file so
|
||||||
|
if(aFile)
|
||||||
|
{
|
||||||
|
fclose(aFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aReturnLength > 0 ? aReturnLength - 1 : 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
40
src/interfaces/odbc/gpps.h
Normal file
40
src/interfaces/odbc/gpps.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// GetPrivateProfileString
|
||||||
|
// for UNIX use
|
||||||
|
#ifndef GPPS_H
|
||||||
|
#define GPPS_H
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "iodbc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
GetPrivateProfileString(char *theSection, // section name
|
||||||
|
char *theKey, // search key name
|
||||||
|
char *theDefault, // default value if not found
|
||||||
|
char *theReturnBuffer, // return valuse stored here
|
||||||
|
size_t theBufferLength, // byte length of return buffer
|
||||||
|
char *theIniFileName); // pathname of ini file to search
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WritePrivateProfileString(char *theSection, // section name
|
||||||
|
char *theKey, // write key name
|
||||||
|
char *theBuffer, // input buffer
|
||||||
|
char *theIniFileName); // pathname of ini file to write
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#undef DWORD
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -16,12 +16,24 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tuple.h"
|
#include "tuple.h"
|
||||||
#include "pgtypes.h"
|
#include "pgtypes.h"
|
||||||
|
|
||||||
@ -282,7 +294,7 @@ char *p;
|
|||||||
// examples of identifiers. it says return a blank for no
|
// examples of identifiers. it says return a blank for no
|
||||||
// quote character, we'll try that...
|
// quote character, we'll try that...
|
||||||
if (pcbInfoValue) *pcbInfoValue = 1;
|
if (pcbInfoValue) *pcbInfoValue = 1;
|
||||||
strncpy_null((char *)rgbInfoValue, " ", (size_t)cbInfoValueMax);
|
strncpy_null((char *)rgbInfoValue, "\"", (size_t)cbInfoValueMax);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_KEYWORDS: /* ODBC 2.0 */
|
case SQL_KEYWORDS: /* ODBC 2.0 */
|
||||||
@ -325,7 +337,7 @@ char *p;
|
|||||||
|
|
||||||
case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
|
case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
|
||||||
// maximum length of a column name
|
// maximum length of a column name
|
||||||
*((WORD *)rgbInfoValue) = 32;
|
*((WORD *)rgbInfoValue) = MAX_COLUMN_LEN;
|
||||||
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -358,7 +370,7 @@ char *p;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
|
case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
|
||||||
*((WORD *)rgbInfoValue) = 32;
|
*((WORD *)rgbInfoValue) = MAX_CURSOR_LEN;
|
||||||
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -405,7 +417,7 @@ char *p;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
|
case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
|
||||||
*((WORD *)rgbInfoValue) = 32;
|
*((WORD *)rgbInfoValue) = MAX_TABLE_LEN;
|
||||||
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
if(pcbInfoValue) { *pcbInfoValue = 2; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1036,7 +1048,7 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
|
|||||||
show_regular_tables = FALSE;
|
show_regular_tables = FALSE;
|
||||||
show_views = FALSE;
|
show_views = FALSE;
|
||||||
|
|
||||||
// make_string mallocs memory
|
/* make_string mallocs memory */
|
||||||
tableType = make_string(szTableType, cbTableType, NULL);
|
tableType = make_string(szTableType, cbTableType, NULL);
|
||||||
if (tableType) {
|
if (tableType) {
|
||||||
strcpy(table_types, tableType);
|
strcpy(table_types, tableType);
|
||||||
@ -1059,7 +1071,10 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
|
|||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
show_regular_tables = TRUE;
|
||||||
|
show_views = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not interested in SYSTEM TABLES then filter them out
|
/* If not interested in SYSTEM TABLES then filter them out
|
||||||
@ -1228,6 +1243,9 @@ mylog("**** SQLTables(): ENTER, stmt=%u\n", stmt);
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API SQLColumns(
|
RETCODE SQL_API SQLColumns(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
UCHAR FAR * szTableQualifier,
|
UCHAR FAR * szTableQualifier,
|
||||||
@ -1247,9 +1265,8 @@ StatementClass *col_stmt;
|
|||||||
char columns_query[MAX_STATEMENT_LEN];
|
char columns_query[MAX_STATEMENT_LEN];
|
||||||
RETCODE result;
|
RETCODE result;
|
||||||
char table_owner[MAX_INFO_STRING], table_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING], field_type_name[MAX_INFO_STRING];
|
char table_owner[MAX_INFO_STRING], table_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING], field_type_name[MAX_INFO_STRING];
|
||||||
Int2 field_number, field_length, mod_length;
|
Int2 field_number, field_length, mod_length, result_cols;
|
||||||
Int4 field_type;
|
Int4 field_type, the_type;
|
||||||
Int2 the_type;
|
|
||||||
char not_null[MAX_INFO_STRING];
|
char not_null[MAX_INFO_STRING];
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
|
|
||||||
@ -1403,10 +1420,11 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
|
|
||||||
// the binding structure for a statement is not set up until
|
// the binding structure for a statement is not set up until
|
||||||
// a statement is actually executed, so we'll have to do this ourselves.
|
// a statement is actually executed, so we'll have to do this ourselves.
|
||||||
extend_bindings(stmt, 12);
|
result_cols = 14;
|
||||||
|
extend_bindings(stmt, result_cols);
|
||||||
|
|
||||||
// set the field names
|
// set the field names
|
||||||
QR_set_num_fields(stmt->result, 12);
|
QR_set_num_fields(stmt->result, result_cols);
|
||||||
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
@ -1420,6 +1438,10 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
|
QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
|
||||||
QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
|
QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
|
||||||
|
|
||||||
|
// User defined fields
|
||||||
|
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);
|
result = SQLFetch(hcol_stmt);
|
||||||
|
|
||||||
@ -1435,7 +1457,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
/* For OID fields */
|
/* For OID fields */
|
||||||
the_type = PG_TYPE_OID;
|
the_type = PG_TYPE_OID;
|
||||||
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
||||||
(12 - 1) * sizeof(TupleField));
|
(result_cols - 1) * sizeof(TupleField));
|
||||||
|
|
||||||
set_tuplefield_string(&row->tuple[0], "");
|
set_tuplefield_string(&row->tuple[0], "");
|
||||||
// see note in SQLTables()
|
// see note in SQLTables()
|
||||||
@ -1446,16 +1468,17 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
|
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type));
|
||||||
set_tuplefield_string(&row->tuple[5], "OID");
|
set_tuplefield_string(&row->tuple[5], "OID");
|
||||||
|
|
||||||
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC,
|
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
|
||||||
PG_STATIC));
|
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC, PG_STATIC));
|
||||||
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, the_type, PG_STATIC,
|
|
||||||
PG_STATIC));
|
|
||||||
|
|
||||||
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type));
|
set_nullfield_int2(&row->tuple[8], pgtype_scale(stmt, the_type));
|
||||||
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
|
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
|
||||||
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
|
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
|
||||||
set_tuplefield_string(&row->tuple[11], "");
|
set_tuplefield_string(&row->tuple[11], "");
|
||||||
|
|
||||||
|
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
|
||||||
|
set_tuplefield_int4(&row->tuple[13], the_type);
|
||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
QR_add_tuple(stmt->result, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1463,7 +1486,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
|
|
||||||
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) {
|
while((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO)) {
|
||||||
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
||||||
(12 - 1) * sizeof(TupleField));
|
(result_cols - 1) * sizeof(TupleField));
|
||||||
|
|
||||||
set_tuplefield_string(&row->tuple[0], "");
|
set_tuplefield_string(&row->tuple[0], "");
|
||||||
// see note in SQLTables()
|
// see note in SQLTables()
|
||||||
@ -1494,11 +1517,13 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
|
|
||||||
set_tuplefield_int4(&row->tuple[7], mod_length);
|
set_tuplefield_int4(&row->tuple[7], mod_length);
|
||||||
set_tuplefield_int4(&row->tuple[6], mod_length);
|
set_tuplefield_int4(&row->tuple[6], mod_length);
|
||||||
|
set_tuplefield_int4(&row->tuple[12], mod_length);
|
||||||
} else {
|
} else {
|
||||||
mylog("SQLColumns: field type is OTHER: field_type = %d, pgtype_length = %d\n", field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
|
mylog("SQLColumns: field type is OTHER: field_type = %d, pgtype_length = %d\n", field_type, pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
|
||||||
|
|
||||||
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
|
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, field_type, PG_STATIC, PG_STATIC));
|
||||||
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, field_type, PG_STATIC, PG_STATIC));
|
set_tuplefield_int4(&row->tuple[6], pgtype_precision(stmt, field_type, PG_STATIC, PG_STATIC));
|
||||||
|
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1506,6 +1531,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
|
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
|
||||||
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
|
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
|
||||||
set_tuplefield_string(&row->tuple[11], "");
|
set_tuplefield_string(&row->tuple[11], "");
|
||||||
|
set_tuplefield_int4(&row->tuple[13], field_type);
|
||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
QR_add_tuple(stmt->result, row);
|
||||||
|
|
||||||
@ -1526,7 +1552,7 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
the_type = PG_TYPE_INT4;
|
the_type = PG_TYPE_INT4;
|
||||||
|
|
||||||
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
row = (TupleNode *)malloc(sizeof(TupleNode) +
|
||||||
(12 - 1) * sizeof(TupleField));
|
(result_cols - 1) * sizeof(TupleField));
|
||||||
|
|
||||||
set_tuplefield_string(&row->tuple[0], "");
|
set_tuplefield_string(&row->tuple[0], "");
|
||||||
set_tuplefield_string(&row->tuple[1], "");
|
set_tuplefield_string(&row->tuple[1], "");
|
||||||
@ -1540,6 +1566,8 @@ mylog("**** SQLColumns(): ENTER, stmt=%u\n", stmt);
|
|||||||
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
|
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, the_type));
|
||||||
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
|
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
|
||||||
set_tuplefield_string(&row->tuple[11], "");
|
set_tuplefield_string(&row->tuple[11], "");
|
||||||
|
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
|
||||||
|
set_tuplefield_int4(&row->tuple[13], the_type);
|
||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
QR_add_tuple(stmt->result, row);
|
||||||
}
|
}
|
||||||
|
66
src/interfaces/odbc/iodbc.h
Normal file
66
src/interfaces/odbc/iodbc.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef _IODBC_H
|
||||||
|
#define _IODBC_H
|
||||||
|
|
||||||
|
# if !defined(WINDOWS) && !defined(WIN32_SYSTEM)
|
||||||
|
# define _UNIX_
|
||||||
|
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
|
||||||
|
# define MEM_ALLOC(size) (malloc((size_t)(size)))
|
||||||
|
# define MEM_FREE(ptr) {if(ptr) free(ptr);}
|
||||||
|
|
||||||
|
# define STRCPY(t, s) (strcpy((char*)(t), (char*)(s)))
|
||||||
|
# define STRNCPY(t,s,n) (strncpy((char*)(t), (char*)(s), (size_t)(n)))
|
||||||
|
# define STRCAT(t, s) (strcat((char*)(t), (char*)(s)))
|
||||||
|
# define STRNCAT(t,s,n) (strncat((char*)(t), (char*)(s), (size_t)(n)))
|
||||||
|
# define STREQ(a, b) (strcmp((char*)(a), (char*)(b)) == 0)
|
||||||
|
# define STRLEN(str) ((str)? strlen((char*)(str)):0)
|
||||||
|
|
||||||
|
# define EXPORT
|
||||||
|
# define CALLBACK
|
||||||
|
# define FAR
|
||||||
|
|
||||||
|
typedef signed short SSHOR;
|
||||||
|
typedef short WORD;
|
||||||
|
typedef long DWORD;
|
||||||
|
|
||||||
|
typedef WORD WPARAM;
|
||||||
|
typedef DWORD LPARAM;
|
||||||
|
typedef void* HWND;
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
# endif /* _UNIX_ */
|
||||||
|
|
||||||
|
# if defined(WINDOWS) || defined(WIN32_SYSTEM)
|
||||||
|
|
||||||
|
# include <windows.h>
|
||||||
|
# include <windowsx.h>
|
||||||
|
|
||||||
|
# ifdef _MSVC_
|
||||||
|
# define MEM_ALLOC(size) (fmalloc((size_t)(size)))
|
||||||
|
# define MEM_FREE(ptr) ((ptr)? ffree((PTR)(ptr)):0))
|
||||||
|
# define STRCPY(t, s) (fstrcpy((char FAR*)(t), (char FAR*)(s)))
|
||||||
|
# define STRNCPY(t,s,n) (fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n)))
|
||||||
|
# define STRLEN(str) ((str)? fstrlen((char FAR*)(str)):0)
|
||||||
|
# define STREQ(a, b) (fstrcmp((char FAR*)(a), (char FAR*)(b) == 0)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef _BORLAND_
|
||||||
|
# define MEM_ALLOC(size) (farmalloc((unsigned long)(size))
|
||||||
|
# define MEM_FREE(ptr) ((ptr)? farfree((void far*)(ptr)):0)
|
||||||
|
# define STRCPY(t, s) (_fstrcpy((char FAR*)(t), (char FAR*)(s)))
|
||||||
|
# define STRNCPY(t,s,n) (_fstrncpy((char FAR*)(t), (char FAR*)(s), (size_t)(n)))
|
||||||
|
# define STRLEN(str) ((str)? _fstrlen((char FAR*)(str)):0)
|
||||||
|
# define STREQ(a, b) (_fstrcmp((char FAR*)(a), (char FAR*)(b) == 0)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# endif /* WINDOWS */
|
||||||
|
|
||||||
|
# define SYSERR (-1)
|
||||||
|
|
||||||
|
# ifndef NULL
|
||||||
|
# define NULL ((void FAR*)0UL)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
237
src/interfaces/odbc/isql.h
Normal file
237
src/interfaces/odbc/isql.h
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/* Modified isql.h file from iodbc. This file should be placed in the
|
||||||
|
* include path to be used to create ODBC compliant applications.
|
||||||
|
*/
|
||||||
|
#ifndef _INTRINSIC_SQL_H
|
||||||
|
# define _INTRINSIC_SQL_H
|
||||||
|
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef long int SDWORD;
|
||||||
|
typedef short int SWORD;
|
||||||
|
typedef unsigned long int UDWORD;
|
||||||
|
typedef unsigned short int UWORD;
|
||||||
|
|
||||||
|
typedef void FAR* PTR;
|
||||||
|
|
||||||
|
typedef void FAR* HENV;
|
||||||
|
typedef void FAR* HDBC;
|
||||||
|
typedef void FAR* HSTMT;
|
||||||
|
|
||||||
|
typedef signed short RETCODE;
|
||||||
|
|
||||||
|
# ifdef WIN32
|
||||||
|
# define SQL_API __stdcall
|
||||||
|
# else
|
||||||
|
# define SQL_API EXPORT CALLBACK
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define ODBCVER 0x0200
|
||||||
|
|
||||||
|
# define SQL_MAX_MESSAGE_LENGTH 512
|
||||||
|
# define SQL_MAX_DSN_LENGTH 32
|
||||||
|
|
||||||
|
/* return code */
|
||||||
|
# define SQL_INVALID_HANDLE (-2)
|
||||||
|
# define SQL_ERROR (-1)
|
||||||
|
# define SQL_SUCCESS 0
|
||||||
|
# define SQL_SUCCESS_WITH_INFO 1
|
||||||
|
# define SQL_NO_DATA_FOUND 100
|
||||||
|
|
||||||
|
/* standard SQL datatypes (agree with ANSI type numbering) */
|
||||||
|
# define SQL_CHAR 1
|
||||||
|
# define SQL_NUMERIC 2
|
||||||
|
# define SQL_DECIMAL 3
|
||||||
|
# define SQL_INTEGER 4
|
||||||
|
# define SQL_SMALLINT 5
|
||||||
|
# define SQL_FLOAT 6
|
||||||
|
# define SQL_REAL 7
|
||||||
|
# define SQL_DOUBLE 8
|
||||||
|
# define SQL_VARCHAR 12
|
||||||
|
|
||||||
|
# define SQL_TYPE_MIN SQL_CHAR
|
||||||
|
# define SQL_TYPE_NULL 0
|
||||||
|
# define SQL_TYPE_MAX SQL_VARCHAR
|
||||||
|
|
||||||
|
/* C to SQL datatype mapping */
|
||||||
|
# define SQL_C_CHAR SQL_CHAR
|
||||||
|
# define SQL_C_LONG SQL_INTEGER
|
||||||
|
# define SQL_C_SHORT SQL_SMALLINT
|
||||||
|
# define SQL_C_FLOAT SQL_REAL
|
||||||
|
# define SQL_C_DOUBLE SQL_DOUBLE
|
||||||
|
# define SQL_C_DEFAULT 99
|
||||||
|
|
||||||
|
# define SQL_NO_NULLS 0
|
||||||
|
# define SQL_NULLABLE 1
|
||||||
|
# define SQL_NULLABLE_UNKNOWN 2
|
||||||
|
|
||||||
|
/* some special length values */
|
||||||
|
# define SQL_NULL_DATA (-1)
|
||||||
|
# define SQL_DATA_AT_EXEC (-2)
|
||||||
|
# define SQL_NTS (-3)
|
||||||
|
|
||||||
|
/* SQLFreeStmt flag values */
|
||||||
|
# define SQL_CLOSE 0
|
||||||
|
# define SQL_DROP 1
|
||||||
|
# define SQL_UNBIND 2
|
||||||
|
# define SQL_RESET_PARAMS 3
|
||||||
|
|
||||||
|
/* SQLTransact flag values */
|
||||||
|
# define SQL_COMMIT 0
|
||||||
|
# define SQL_ROLLBACK 1
|
||||||
|
|
||||||
|
/* SQLColAttributes flag values */
|
||||||
|
# define SQL_COLUMN_COUNT 0
|
||||||
|
# define SQL_COLUMN_LABEL 18
|
||||||
|
# define SQL_COLATT_OPT_MAX SQL_COLUMN_LABEL
|
||||||
|
# define SQL_COLUMN_DRIVER_START 1000
|
||||||
|
|
||||||
|
# define SQL_COLATT_OPT_MIN SQL_COLUMN_COUNT
|
||||||
|
|
||||||
|
/* Null handles */
|
||||||
|
# define SQL_NULL_HENV 0
|
||||||
|
# define SQL_NULL_HDBC 0
|
||||||
|
# define SQL_NULL_HSTMT 0
|
||||||
|
|
||||||
|
/* All code below has been added to the original isql.h coming from iodbc */
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
|
||||||
|
/* More SQLColAttributes flag values */
|
||||||
|
#define SQL_COLUMN_NAME 1
|
||||||
|
#define SQL_COLUMN_TYPE 2
|
||||||
|
#define SQL_COLUMN_LENGTH 3
|
||||||
|
#define SQL_COLUMN_PRECISION 4
|
||||||
|
#define SQL_COLUMN_SCALE 5
|
||||||
|
#define SQL_COLUMN_DISPLAY_SIZE 6
|
||||||
|
#define SQL_COLUMN_NULLABLE 7
|
||||||
|
#define SQL_COLUMN_UNSIGNED 8
|
||||||
|
#define SQL_COLUMN_MONEY 9
|
||||||
|
#define SQL_COLUMN_UPDATABLE 10
|
||||||
|
#define SQL_COLUMN_AUTO_INCREMENT 11
|
||||||
|
#define SQL_COLUMN_CASE_SENSITIVE 12
|
||||||
|
#define SQL_COLUMN_SEARCHABLE 13
|
||||||
|
#define SQL_COLUMN_TYPE_NAME 14
|
||||||
|
#define SQL_COLUMN_TABLE_NAME 15
|
||||||
|
#define SQL_COLUMN_OWNER_NAME 16
|
||||||
|
#define SQL_COLUMN_QUALIFIER_NAME 17
|
||||||
|
|
||||||
|
/* SQLColAttributes Searchable flags */
|
||||||
|
#define SQL_UNSEARCHABLE 0
|
||||||
|
#define SQL_LIKE_ONLY 1
|
||||||
|
#define SQL_ALL_EXCEPT_LIKE 2
|
||||||
|
#define SQL_SEARCHABLE 3
|
||||||
|
#define SQL_PRED_SEARCHABLE SQL_SEARCHABLE
|
||||||
|
|
||||||
|
/* SQLColAttributes Updateable flags */
|
||||||
|
#define SQL_ATTR_READONLY 0
|
||||||
|
#define SQL_ATTR_WRITE 1
|
||||||
|
#define SQL_ATTR_READWRITE_UNKNOWN 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* function prototypes previously not contained in isql.h
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLAllocConnect (HENV henv,
|
||||||
|
HDBC FAR * phdbc);
|
||||||
|
RETCODE SQL_API SQLAllocEnv (HENV FAR * phenv);
|
||||||
|
RETCODE SQL_API SQLAllocStmt (HDBC hdbc,
|
||||||
|
HSTMT FAR * phstmt);
|
||||||
|
RETCODE SQL_API SQLBindCol (HSTMT hstmt,
|
||||||
|
UWORD icol,
|
||||||
|
SWORD fCType,
|
||||||
|
PTR rgbValue,
|
||||||
|
SDWORD cbValueMax,
|
||||||
|
SDWORD FAR * pcbValue);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLCancel (HSTMT hstmt);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLColAttributes (HSTMT hstmt,
|
||||||
|
UWORD icol,
|
||||||
|
UWORD fDescType,
|
||||||
|
PTR rgbDesc,
|
||||||
|
SWORD cbDescMax,
|
||||||
|
SWORD FAR * pcbDesc,
|
||||||
|
SDWORD FAR * pfDesc);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLConnect (HDBC hdbc,
|
||||||
|
UCHAR FAR * szDSN,
|
||||||
|
SWORD cbDSN,
|
||||||
|
UCHAR FAR * szUID,
|
||||||
|
SWORD cbUID,
|
||||||
|
UCHAR FAR * szAuthStr,
|
||||||
|
SWORD cbAuthStr);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLDescribeCol (HSTMT hstmt,
|
||||||
|
UWORD icol,
|
||||||
|
UCHAR FAR * szColName,
|
||||||
|
SWORD cbColNameMax,
|
||||||
|
SWORD FAR * pcbColName,
|
||||||
|
SWORD FAR * pfSqlType,
|
||||||
|
UDWORD FAR * pcbColDef,
|
||||||
|
SWORD FAR * pibScale,
|
||||||
|
SWORD FAR * pfNullable);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLDisconnect (HDBC hdbc);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLError (HENV henv,
|
||||||
|
HDBC hdbc,
|
||||||
|
HSTMT hstmt,
|
||||||
|
UCHAR FAR * szSqlState,
|
||||||
|
SDWORD FAR * pfNativeError,
|
||||||
|
UCHAR FAR * szErrorMsg,
|
||||||
|
SWORD cbErrorMsgMax,
|
||||||
|
SWORD FAR * pcbErrorMsg);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLExecDirect (HSTMT hstmt,
|
||||||
|
UCHAR FAR * szSqlStr,
|
||||||
|
SDWORD cbSqlStr);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLExecute (HSTMT hstmt);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFetch (HSTMT hstmt);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFreeConnect (HDBC hdbc);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFreeEnv (HENV henv);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFreeStmt (HSTMT hstmt,
|
||||||
|
UWORD fOption);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLGetCursorName (HSTMT hstmt,
|
||||||
|
UCHAR FAR * szCursor,
|
||||||
|
SWORD cbCursorMax,
|
||||||
|
SWORD FAR * pcbCursor);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLNumResultCols (HSTMT hstmt,
|
||||||
|
SWORD FAR * pccol);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLPrepare (HSTMT hstmt,
|
||||||
|
UCHAR FAR * szSqlStr,
|
||||||
|
SDWORD cbSqlStr);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLRowCount (HSTMT hstmt,
|
||||||
|
SDWORD FAR * pcrow);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLSetCursorName (HSTMT hstmt,
|
||||||
|
UCHAR FAR * szCursor,
|
||||||
|
SWORD cbCursor);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLTransact (HENV henv,
|
||||||
|
HDBC hdbc,
|
||||||
|
UWORD fType);
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLSetParam (HSTMT hstmt,
|
||||||
|
UWORD ipar,
|
||||||
|
SWORD fCType,
|
||||||
|
SWORD fSqlType,
|
||||||
|
UDWORD cbColDef,
|
||||||
|
SWORD ibScale,
|
||||||
|
PTR rgbValue,
|
||||||
|
SDWORD FAR * pcbValue);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
1539
src/interfaces/odbc/isqlext.h
Normal file
1539
src/interfaces/odbc/isqlext.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
typedef struct lo_arg {
|
struct lo_arg {
|
||||||
int isint;
|
int isint;
|
||||||
int len;
|
int len;
|
||||||
union
|
union
|
||||||
|
@ -37,7 +37,7 @@ static FILE *LOGFP = 0;
|
|||||||
fmt = va_arg(args, char *);
|
fmt = va_arg(args, char *);
|
||||||
|
|
||||||
if (! LOGFP) {
|
if (! LOGFP) {
|
||||||
LOGFP = fopen("c:\\mylog.log", "w");
|
LOGFP = fopen(MYLOGFILE, "w");
|
||||||
setbuf(LOGFP, NULL);
|
setbuf(LOGFP, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ static FILE *LOGFP = 0;
|
|||||||
fmt = va_arg(args, char *);
|
fmt = va_arg(args, char *);
|
||||||
|
|
||||||
if (! LOGFP) {
|
if (! LOGFP) {
|
||||||
LOGFP = fopen("c:\\psqlodbc.log", "w");
|
LOGFP = fopen(QLOGFILE, "w");
|
||||||
setbuf(LOGFP, NULL);
|
setbuf(LOGFP, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,12 +77,24 @@ static FILE *LOGFP = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Undefine these because windows.h will redefine and cause a warning */
|
/* Undefine these because windows.h will redefine and cause a warning */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UNIX
|
||||||
#undef va_start
|
#undef va_start
|
||||||
#undef va_end
|
#undef va_end
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */
|
/* returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied (not including null term) */
|
||||||
int
|
int
|
||||||
@ -155,7 +167,7 @@ make_string(char *s, int len, char *buf)
|
|||||||
int length;
|
int length;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
if(s && (len > 0 || len == SQL_NTS)) {
|
if(s && (len > 0 || (len == SQL_NTS && strlen(s) > 0))) {
|
||||||
length = (len > 0) ? len : strlen(s);
|
length = (len > 0) ? len : strlen(s);
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
@ -10,6 +10,15 @@
|
|||||||
#ifndef __MISC_H__
|
#ifndef __MISC_H__
|
||||||
#define __MISC_H__
|
#define __MISC_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include "gpps.h"
|
||||||
|
#define SQLGetPrivateProfileString(a,b,c,d,e,f) GetPrivateProfileString(a,b,c,d,e,f)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* Uncomment MY_LOG define to compile in the mylog() statements.
|
/* Uncomment MY_LOG define to compile in the mylog() statements.
|
||||||
@ -30,12 +39,22 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef MY_LOG
|
#ifdef MY_LOG
|
||||||
|
#ifdef UNIX
|
||||||
|
#define MYLOGFILE "/tmp/mylog.log"
|
||||||
|
#else
|
||||||
|
#define MYLOGFILE "c:\\mylog.log"
|
||||||
|
#endif
|
||||||
void mylog(); /* prototype */
|
void mylog(); /* prototype */
|
||||||
#else
|
#else
|
||||||
#define mylog // mylog
|
#define mylog // mylog
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_LOG
|
#ifdef Q_LOG
|
||||||
|
#ifdef UNIX
|
||||||
|
#define QLOGFILE "/tmp/psqlodbc.log"
|
||||||
|
#else
|
||||||
|
#define QLOGFILE "c:\\psqlodbc.log"
|
||||||
|
#endif
|
||||||
void qlog(); /* prototype */
|
void qlog(); /* prototype */
|
||||||
#else
|
#else
|
||||||
#define qlog // qlog
|
#define qlog // qlog
|
||||||
|
3
src/interfaces/odbc/odbcinst.ini
Normal file
3
src/interfaces/odbc/odbcinst.ini
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[PostgreSQL]
|
||||||
|
Debug = 0
|
||||||
|
CommLog = 1
|
@ -13,10 +13,22 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
@ -81,12 +93,15 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
|
|||||||
case SQL_ACCESS_MODE:
|
case SQL_ACCESS_MODE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SQL_TXN_ISOLATION:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char option[32];
|
char option[64];
|
||||||
conn->errormsg = "This option is currently unsupported by the driver";
|
conn->errormsg = "Driver does not support setting this connect option";
|
||||||
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
||||||
sprintf(option, "fOption=%d", fOption);
|
sprintf(option, "fOption=%d, vParam=%d", fOption, vParam);
|
||||||
CC_log_error(func, option, conn);
|
CC_log_error(func, option, conn);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
@ -126,8 +141,8 @@ ConnectionClass *conn = (ConnectionClass *) hdbc;
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char option[32];
|
char option[64];
|
||||||
conn->errormsg = "This option is currently unsupported by the driver";
|
conn->errormsg = "Driver does not support getting this connect option";
|
||||||
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
conn->errornumber = CONN_UNSUPPORTED_OPTION;
|
||||||
sprintf(option, "fOption=%d", fOption);
|
sprintf(option, "fOption=%d", fOption);
|
||||||
CC_log_error(func, option, conn);
|
CC_log_error(func, option, conn);
|
||||||
@ -242,10 +257,10 @@ char changed = FALSE;
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char option[32];
|
char option[64];
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
||||||
stmt->errormsg = "Driver does not support this statement option";
|
stmt->errormsg = "Driver does not support setting this statement option";
|
||||||
sprintf(option, "fOption=%d", fOption);
|
sprintf(option, "fOption=%d, vParam=%d", fOption, vParam);
|
||||||
SC_log_error(func, option, stmt);
|
SC_log_error(func, option, stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
@ -326,9 +341,9 @@ StatementClass *stmt = (StatementClass *) hstmt;
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
char option[32];
|
char option[64];
|
||||||
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
||||||
stmt->errormsg = "Driver does not support this statement option";
|
stmt->errormsg = "Driver does not support getting this statement option";
|
||||||
sprintf(option, "fOption=%d", fOption);
|
sprintf(option, "fOption=%d", fOption);
|
||||||
SC_log_error(func, option, stmt);
|
SC_log_error(func, option, stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
|
775
src/interfaces/odbc/parse.c
Normal file
775
src/interfaces/odbc/parse.c
Normal file
@ -0,0 +1,775 @@
|
|||||||
|
|
||||||
|
/* Module: parse.c
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "statement.h"
|
||||||
|
#include "connection.h"
|
||||||
|
#include "qresult.h"
|
||||||
|
#include "pgtypes.h"
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#if !HAVE_STRICMP
|
||||||
|
#define stricmp(s1,s2) strcasecmp(s1,s2)
|
||||||
|
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FLD_INCR 32
|
||||||
|
#define TAB_INCR 8
|
||||||
|
#define COL_INCR 16
|
||||||
|
|
||||||
|
char *
|
||||||
|
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int out = 0;
|
||||||
|
char qc, in_escape = FALSE;
|
||||||
|
|
||||||
|
if (smax <= 1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
smax--;
|
||||||
|
|
||||||
|
/* skip leading delimiters */
|
||||||
|
while (isspace(s[i]) || s[i] == ',') {
|
||||||
|
// mylog("skipping '%c'\n", s[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s[0] == '\0') {
|
||||||
|
token[0] = '\0';
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quote) *quote = FALSE;
|
||||||
|
if (dquote) *dquote = FALSE;
|
||||||
|
if (numeric) *numeric = FALSE;
|
||||||
|
|
||||||
|
/* get the next token */
|
||||||
|
while ( ! isspace(s[i]) && s[i] != ',' && s[i] != '\0' && out != smax) {
|
||||||
|
|
||||||
|
/* Handle quoted stuff */
|
||||||
|
if ( out == 0 && (s[i] == '\"' || s[i] == '\'')) {
|
||||||
|
qc = s[i];
|
||||||
|
if (qc == '\"') {
|
||||||
|
if (dquote) *dquote = TRUE;
|
||||||
|
}
|
||||||
|
if (qc == '\'') {
|
||||||
|
if (quote) *quote = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++; /* dont return the quote */
|
||||||
|
while (s[i] != '\0' && out != smax) {
|
||||||
|
if (s[i] == qc && ! in_escape) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s[i] == '\\' && ! in_escape) {
|
||||||
|
in_escape = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
in_escape = FALSE;
|
||||||
|
token[out++] = s[i];
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (s[i] == qc)
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for numeric literals */
|
||||||
|
if ( out == 0 && isdigit(s[i])) {
|
||||||
|
if (numeric) *numeric = TRUE;
|
||||||
|
token[out++] = s[i++];
|
||||||
|
while ( isalnum(s[i]) || s[i] == '.')
|
||||||
|
token[out++] = s[i++];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ispunct(s[i])) {
|
||||||
|
if (out == 0) {
|
||||||
|
token[out++] = s[i++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out != smax)
|
||||||
|
token[out++] = s[i];
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mylog("done -- s[%d] = '%c'\n", i, s[i]);
|
||||||
|
|
||||||
|
token[out] = '\0';
|
||||||
|
|
||||||
|
/* find the delimiter */
|
||||||
|
while ( isspace(s[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/* return the most priority delimiter */
|
||||||
|
if (s[i] == ',') {
|
||||||
|
if (delim) *delim = s[i];
|
||||||
|
}
|
||||||
|
else if (s[i] == '\0') {
|
||||||
|
if (delim) *delim = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (delim) *delim = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip trailing blanks */
|
||||||
|
while ( isspace(s[i])) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
QR_set_num_fields(stmt->result, 14);
|
||||||
|
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
|
||||||
|
QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
||||||
|
QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
|
||||||
|
QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
|
||||||
|
QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
|
||||||
|
QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
|
||||||
|
QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
|
||||||
|
QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
|
||||||
|
// User defined fields
|
||||||
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
|
||||||
|
{
|
||||||
|
if (fi->name[0] == '\0')
|
||||||
|
strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
|
||||||
|
|
||||||
|
fi->type = atoi( QR_get_value_manual(col_info->result, k, 13));
|
||||||
|
fi->precision = atoi( QR_get_value_manual(col_info->result, k, 6));
|
||||||
|
fi->length = atoi( QR_get_value_manual(col_info->result, k, 7));
|
||||||
|
fi->nullable = atoi( QR_get_value_manual(col_info->result, k, 10));
|
||||||
|
fi->display_size = atoi( QR_get_value_manual(col_info->result, k, 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
char *col;
|
||||||
|
|
||||||
|
|
||||||
|
for (k = 0; k < QR_get_num_tuples(col_info->result); k++) {
|
||||||
|
col = QR_get_value_manual(col_info->result, k, 3);
|
||||||
|
if ( ! strcmp(col, fi->name)) {
|
||||||
|
getColInfo(col_info, fi, k);
|
||||||
|
|
||||||
|
mylog("PARSE: searchColInfo: \n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char
|
||||||
|
parse_statement(StatementClass *stmt)
|
||||||
|
{
|
||||||
|
char token[256];
|
||||||
|
char delim, quote, dquote, numeric, unquoted;
|
||||||
|
char *ptr;
|
||||||
|
char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE;
|
||||||
|
char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE;
|
||||||
|
int j, i, k, n, blevel = 0;
|
||||||
|
FIELD_INFO **fi;
|
||||||
|
TABLE_INFO **ti;
|
||||||
|
char parse;
|
||||||
|
ConnectionClass *conn = stmt->hdbc;
|
||||||
|
HSTMT hcol_stmt;
|
||||||
|
StatementClass *col_stmt;
|
||||||
|
RETCODE result;
|
||||||
|
|
||||||
|
|
||||||
|
ptr = stmt->statement;
|
||||||
|
fi = stmt->fi;
|
||||||
|
ti = stmt->ti;
|
||||||
|
|
||||||
|
stmt->nfld = 0;
|
||||||
|
stmt->ntab = 0;
|
||||||
|
|
||||||
|
while (ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if ( unquoted && ! stricmp(token, "select")) {
|
||||||
|
in_select = TRUE;
|
||||||
|
|
||||||
|
mylog("SELECT\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( unquoted && in_select && ! stricmp(token, "distinct")) {
|
||||||
|
in_distinct = TRUE;
|
||||||
|
|
||||||
|
mylog("DISTINCT\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( unquoted && ! stricmp(token, "into")) {
|
||||||
|
in_select = FALSE;
|
||||||
|
|
||||||
|
mylog("INTO\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( unquoted && ! stricmp(token, "from")) {
|
||||||
|
in_select = FALSE;
|
||||||
|
in_from = TRUE;
|
||||||
|
|
||||||
|
mylog("FROM\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( unquoted && (! stricmp(token, "where") ||
|
||||||
|
! stricmp(token, "union") ||
|
||||||
|
! stricmp(token, "order") ||
|
||||||
|
! stricmp(token, "group") ||
|
||||||
|
! stricmp(token, "having"))) {
|
||||||
|
|
||||||
|
in_select = FALSE;
|
||||||
|
in_from = FALSE;
|
||||||
|
in_where = TRUE;
|
||||||
|
|
||||||
|
mylog("WHERE...\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_select) {
|
||||||
|
|
||||||
|
if ( in_distinct) {
|
||||||
|
mylog("in distinct\n");
|
||||||
|
|
||||||
|
if (unquoted && ! stricmp(token, "on")) {
|
||||||
|
in_on = TRUE;
|
||||||
|
mylog("got on\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (in_on) {
|
||||||
|
in_distinct = FALSE;
|
||||||
|
in_on = FALSE;
|
||||||
|
continue; /* just skip the unique on field */
|
||||||
|
}
|
||||||
|
mylog("done distinct\n");
|
||||||
|
in_distinct = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( in_expr || in_func) { /* just eat the expression */
|
||||||
|
mylog("in_expr=%d or func=%d\n", in_expr, in_func);
|
||||||
|
if (quote || dquote)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (in_expr && blevel == 0 && delim == ',') {
|
||||||
|
mylog("**** in_expr and Got comma\n");
|
||||||
|
in_expr = FALSE;
|
||||||
|
in_field = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (token[0] == '(') {
|
||||||
|
blevel++;
|
||||||
|
mylog("blevel++ = %d\n", blevel);
|
||||||
|
}
|
||||||
|
else if (token[0] == ')') {
|
||||||
|
blevel--;
|
||||||
|
mylog("blevel-- = %d\n", blevel);
|
||||||
|
if (delim==',') {
|
||||||
|
in_func = FALSE;
|
||||||
|
in_expr = FALSE;
|
||||||
|
in_field = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! in_field) {
|
||||||
|
|
||||||
|
if ( ! token[0])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! (stmt->nfld % FLD_INCR)) {
|
||||||
|
mylog("reallocing at nfld=%d\n", stmt->nfld);
|
||||||
|
fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *));
|
||||||
|
if ( ! fi) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
stmt->fi = fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
fi[stmt->nfld] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
|
||||||
|
if (fi[stmt->nfld] == NULL) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the field info */
|
||||||
|
memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO));
|
||||||
|
|
||||||
|
/* double quotes are for qualifiers */
|
||||||
|
if (dquote)
|
||||||
|
fi[stmt->nfld]->dquote = TRUE;
|
||||||
|
|
||||||
|
if (quote) {
|
||||||
|
fi[stmt->nfld++]->quote = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (numeric) {
|
||||||
|
mylog("**** got numeric: nfld = %d\n", stmt->nfld);
|
||||||
|
fi[stmt->nfld]->numeric = TRUE;
|
||||||
|
}
|
||||||
|
else if (token[0] == '(') { /* expression */
|
||||||
|
mylog("got EXPRESSION\n");
|
||||||
|
fi[stmt->nfld++]->expr = TRUE;
|
||||||
|
in_expr = TRUE;
|
||||||
|
blevel = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
strcpy(fi[stmt->nfld]->name, token);
|
||||||
|
fi[stmt->nfld]->dot[0] = '\0';
|
||||||
|
}
|
||||||
|
mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot);
|
||||||
|
|
||||||
|
if (delim == ',') {
|
||||||
|
mylog("comma (1)\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
in_field = TRUE;
|
||||||
|
}
|
||||||
|
stmt->nfld++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* We are in a field now */
|
||||||
|
/**************************/
|
||||||
|
if (in_dot) {
|
||||||
|
stmt->nfld--;
|
||||||
|
strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name);
|
||||||
|
strcpy(fi[stmt->nfld]->name, token);
|
||||||
|
stmt->nfld++;
|
||||||
|
in_dot = FALSE;
|
||||||
|
|
||||||
|
if (delim == ',') {
|
||||||
|
mylog("in_dot: got comma\n");
|
||||||
|
in_field = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_as) {
|
||||||
|
stmt->nfld--;
|
||||||
|
strcpy(fi[stmt->nfld]->alias, token);
|
||||||
|
mylog("alias for field '%s' is '%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias);
|
||||||
|
in_as = FALSE;
|
||||||
|
in_field = FALSE;
|
||||||
|
|
||||||
|
stmt->nfld++;
|
||||||
|
|
||||||
|
if (delim == ',') {
|
||||||
|
mylog("comma(2)\n");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function */
|
||||||
|
if (token[0] == '(') {
|
||||||
|
in_func = TRUE;
|
||||||
|
blevel = 1;
|
||||||
|
fi[stmt->nfld-1]->func = TRUE;
|
||||||
|
/* name will have the function name -- maybe useful some day */
|
||||||
|
mylog("**** got function = '%s'\n", fi[stmt->nfld-1]->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token[0] == '.') {
|
||||||
|
in_dot = TRUE;
|
||||||
|
mylog("got dot\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! stricmp(token, "as")) {
|
||||||
|
in_as = TRUE;
|
||||||
|
mylog("got AS\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise, its probably an expression */
|
||||||
|
in_expr = TRUE;
|
||||||
|
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])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! (stmt->ntab % TAB_INCR)) {
|
||||||
|
ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
|
||||||
|
if ( ! ti) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
stmt->ti = ti;
|
||||||
|
}
|
||||||
|
ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO));
|
||||||
|
if (ti[stmt->ntab] == NULL) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ti[stmt->ntab]->alias[0] = '\0';
|
||||||
|
|
||||||
|
strcpy(ti[stmt->ntab]->name, token);
|
||||||
|
mylog("got table = '%s'\n", ti[stmt->ntab]->name);
|
||||||
|
|
||||||
|
if (delim == ',') {
|
||||||
|
mylog("more than 1 tables\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
in_table = TRUE;
|
||||||
|
}
|
||||||
|
stmt->ntab++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(ti[stmt->ntab-1]->alias, token);
|
||||||
|
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab-1]->name, ti[stmt->ntab-1]->alias);
|
||||||
|
in_table = FALSE;
|
||||||
|
if (delim == ',') {
|
||||||
|
mylog("more than 1 tables\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* 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;
|
||||||
|
fi[i]->type = -1;
|
||||||
|
parse = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (fi[i]->quote) { /* handle as text */
|
||||||
|
fi[i]->ti = NULL;
|
||||||
|
fi[i]->type = PG_TYPE_TEXT;
|
||||||
|
fi[i]->precision = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* its a dot, resolve to table or alias */
|
||||||
|
else if (fi[i]->dot[0]) {
|
||||||
|
for (k = 0; k < stmt->ntab; k++) {
|
||||||
|
if ( ! stricmp(ti[k]->name, fi[i]->dot)) {
|
||||||
|
fi[i]->ti = ti[k];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( ! stricmp(ti[k]->alias, fi[i]->dot)) {
|
||||||
|
fi[i]->ti = ti[k];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stmt->ntab == 1)
|
||||||
|
fi[i]->ti = ti[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog("--------------------------------------------\n");
|
||||||
|
mylog("nfld=%d, ntab=%d\n", stmt->nfld, stmt->ntab);
|
||||||
|
|
||||||
|
for (i=0; i < stmt->nfld; i++) {
|
||||||
|
mylog("Field %d: expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'\n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot);
|
||||||
|
if (fi[i]->ti)
|
||||||
|
mylog(" ----> table_name='%s', table_alias='%s'\n", fi[i]->ti->name, fi[i]->ti->alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < stmt->ntab; i++) {
|
||||||
|
mylog("Table %d: name='%s', alias='%s'\n", i, ti[i]->name, ti[i]->alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************/
|
||||||
|
/* 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;
|
||||||
|
for (k = 0; k < conn->ntables; k++) {
|
||||||
|
if ( ! stricmp(conn->col_info[k]->name, ti[i]->name)) {
|
||||||
|
mylog("FOUND col_info table='%s'\n", ti[i]->name);
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! found) {
|
||||||
|
|
||||||
|
mylog("PARSE: Getting SQLColumns for table[%d]='%s'\n", i, ti[i]->name);
|
||||||
|
|
||||||
|
result = SQLAllocStmt( stmt->hdbc, &hcol_stmt);
|
||||||
|
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
|
||||||
|
stmt->errormsg = "SQLAllocStmt failed in parse_statement for columns.";
|
||||||
|
stmt->errornumber = STMT_NO_MEMORY_ERROR;
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
col_stmt = (StatementClass *) hcol_stmt;
|
||||||
|
col_stmt->internal = TRUE;
|
||||||
|
|
||||||
|
result = SQLColumns(hcol_stmt, "", 0, "", 0,
|
||||||
|
ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0);
|
||||||
|
|
||||||
|
mylog(" Past SQLColumns\n");
|
||||||
|
if (result == SQL_SUCCESS) {
|
||||||
|
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 *));
|
||||||
|
if ( ! conn->col_info) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog("PARSE: malloc at conn->col_info[%d]\n", conn->ntables);
|
||||||
|
conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO));
|
||||||
|
if ( ! conn->col_info[conn->ntables]) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the table name and the SQLColumns result structure */
|
||||||
|
strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
|
||||||
|
conn->col_info[conn->ntables]->result = col_stmt->result;
|
||||||
|
|
||||||
|
/* The connection will now free the result structures, so make
|
||||||
|
sure that the statement doesn't free it
|
||||||
|
*/
|
||||||
|
col_stmt->result = NULL;
|
||||||
|
|
||||||
|
conn->ntables++;
|
||||||
|
|
||||||
|
SQLFreeStmt(hcol_stmt, SQL_DROP);
|
||||||
|
mylog("Created col_info table='%s', ntables=%d\n", ti[i]->name, conn->ntables);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SQLFreeStmt(hcol_stmt, SQL_DROP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Associate a table from the statement with a SQLColumn info */
|
||||||
|
ti[i]->col_info = conn->col_info[k];
|
||||||
|
mylog("associate col_info: i=%d, k=%d\n", i, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mylog("Done SQLColumns\n");
|
||||||
|
|
||||||
|
/******************************************************/
|
||||||
|
/* 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) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stars get expanded to all fields in the table */
|
||||||
|
else if (fi[i]->name[0] == '*') {
|
||||||
|
|
||||||
|
char do_all_tables;
|
||||||
|
int total_cols, old_size, need, cols;
|
||||||
|
|
||||||
|
mylog("expanding field %d\n", i);
|
||||||
|
|
||||||
|
total_cols = 0;
|
||||||
|
|
||||||
|
if (fi[i]->ti) /* The star represents only the qualified table */
|
||||||
|
total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result);
|
||||||
|
|
||||||
|
else { /* The star represents all tables */
|
||||||
|
|
||||||
|
/* Calculate the total number of columns after expansion */
|
||||||
|
for (k = 0; k < stmt->ntab; k++) {
|
||||||
|
total_cols += QR_get_num_tuples(ti[k]->col_info->result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total_cols--; /* makes up for the star */
|
||||||
|
|
||||||
|
/* Allocate some more field pointers if necessary */
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
old_size = (stmt->nfld / FLD_INCR * FLD_INCR + FLD_INCR);
|
||||||
|
need = total_cols - (old_size - stmt->nfld);
|
||||||
|
|
||||||
|
mylog("k=%d, total_cols=%d, old_size=%d, need=%d\n", k,total_cols,old_size,need);
|
||||||
|
|
||||||
|
if (need > 0) {
|
||||||
|
int new_size = need / FLD_INCR * FLD_INCR + FLD_INCR;
|
||||||
|
mylog("need more cols: new_size = %d\n", new_size);
|
||||||
|
fi = (FIELD_INFO **) realloc(fi, (old_size + new_size) * sizeof(FIELD_INFO *));
|
||||||
|
if ( ! fi) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// copy any other fields (if there are any) up past the expansion
|
||||||
|
for (j = stmt->nfld - 1; j > i; j--) {
|
||||||
|
mylog("copying field %d to %d\n", j, total_cols + j);
|
||||||
|
fi[total_cols + j] = fi[j];
|
||||||
|
}
|
||||||
|
mylog("done copying fields\n");
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
// Set the new number of fields
|
||||||
|
stmt->nfld += total_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);
|
||||||
|
|
||||||
|
for (n = 0; n < cols; n++) {
|
||||||
|
mylog("creating field info: n=%d\n", n);
|
||||||
|
// skip malloc (already did it for the Star)
|
||||||
|
if (k > 0 || n > 0) {
|
||||||
|
mylog("allocating field info at %d\n", n + i);
|
||||||
|
fi[n + i] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
|
||||||
|
if (fi[n + i] == NULL) {
|
||||||
|
stmt->parse_status = STMT_PARSE_FATAL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Initialize the new space (or the * field) */
|
||||||
|
memset(fi[n + i], 0, sizeof(FIELD_INFO));
|
||||||
|
fi[n + i]->ti = the_ti;
|
||||||
|
|
||||||
|
mylog("about to copy at %d\n", n + i);
|
||||||
|
|
||||||
|
getColInfo(the_ti->col_info, fi[n + i], n);
|
||||||
|
|
||||||
|
mylog("done copying\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
i += cols;
|
||||||
|
mylog("i now at %d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We either know which table the field was in because it was qualified
|
||||||
|
with a table name or alias -OR- there was only 1 table.
|
||||||
|
*/
|
||||||
|
else if (fi[i]->ti) {
|
||||||
|
|
||||||
|
if ( ! searchColInfo(fi[i]->ti->col_info, fi[i]))
|
||||||
|
parse = FALSE;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't know the table -- search all tables in "from" list */
|
||||||
|
else {
|
||||||
|
parse = FALSE;
|
||||||
|
for (k = 0; k < stmt->ntab; k++) {
|
||||||
|
if ( searchColInfo(ti[k]->col_info, fi[i])) {
|
||||||
|
fi[i]->ti = ti[k]; /* now know the table */
|
||||||
|
parse = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -15,15 +15,26 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
#include "pgtypes.h"
|
#include "pgtypes.h"
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "qresult.h"
|
#include "qresult.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
@ -223,7 +234,7 @@ mylog("getCharPrecision: type=%d, col=%d, unknown = %d\n", type,col,handle_unkno
|
|||||||
if (stmt->manual_result) {
|
if (stmt->manual_result) {
|
||||||
flds = result->fields;
|
flds = result->fields;
|
||||||
if (flds)
|
if (flds)
|
||||||
return flds->typlen[col];
|
return flds->adtsize[col];
|
||||||
else
|
else
|
||||||
return maxsize;
|
return maxsize;
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,28 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
HINSTANCE NEAR s_hModule; /* Saved module handle. */
|
|
||||||
GLOBAL_VALUES globals;
|
GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
#ifndef UNIX /* again find a WINDOWS #ifdef */
|
||||||
|
HINSTANCE NEAR s_hModule; /* Saved module handle. */
|
||||||
|
|
||||||
/* This is where the Driver Manager attaches to this Driver */
|
/* This is where the Driver Manager attaches to this Driver */
|
||||||
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||||
@ -72,6 +84,33 @@ WSADATA wsaData;
|
|||||||
UNREFERENCED_PARAMETER(lpReserved);
|
UNREFERENCED_PARAMETER(lpReserved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* UNIX */
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (BOOL)1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (BOOL)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* These two functions do shared library initialziation on UNIX, well at least
|
||||||
|
* on Linux. I don't know about other systems.
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
_init(void)
|
||||||
|
{
|
||||||
|
getGlobalDefaults();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
_fini(void)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function is used to cause the Driver Manager to
|
/* This function is used to cause the Driver Manager to
|
||||||
call functions by number rather than name, which is faster.
|
call functions by number rather than name, which is faster.
|
||||||
The ordinal value of this function must be 199 to have the
|
The ordinal value of this function must be 199 to have the
|
||||||
|
@ -11,10 +11,23 @@
|
|||||||
#ifndef __PSQLODBC_H__
|
#ifndef __PSQLODBC_H__
|
||||||
#define __PSQLODBC_H__
|
#define __PSQLODBC_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#define Int4 long int
|
||||||
|
#define UInt4 unsigned int
|
||||||
|
#define Int2 short
|
||||||
|
#define UInt2 unsigned short
|
||||||
|
typedef float SFLOAT;
|
||||||
|
typedef double SDOUBLE;
|
||||||
|
#else
|
||||||
#define Int4 int
|
#define Int4 int
|
||||||
#define UInt4 unsigned int
|
#define UInt4 unsigned int
|
||||||
#define Int2 short
|
#define Int2 short
|
||||||
#define UInt2 unsigned short
|
#define UInt2 unsigned short
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef UInt4 Oid;
|
typedef UInt4 Oid;
|
||||||
|
|
||||||
@ -31,6 +44,10 @@ typedef UInt4 Oid;
|
|||||||
#define BYTELEN 8
|
#define BYTELEN 8
|
||||||
#define VARHDRSZ sizeof(Int4)
|
#define VARHDRSZ sizeof(Int4)
|
||||||
|
|
||||||
|
#define MAX_TABLE_LEN 32
|
||||||
|
#define MAX_COLUMN_LEN 32
|
||||||
|
#define MAX_CURSOR_LEN 32
|
||||||
|
|
||||||
/* Registry length limits */
|
/* Registry length limits */
|
||||||
#define LARGE_REGISTRY_LEN 4096 /* used for special cases */
|
#define LARGE_REGISTRY_LEN 4096 /* used for special cases */
|
||||||
#define MEDIUM_REGISTRY_LEN 256 /* normal size for user,database,etc. */
|
#define MEDIUM_REGISTRY_LEN 256 /* normal size for user,database,etc. */
|
||||||
@ -50,10 +67,14 @@ typedef UInt4 Oid;
|
|||||||
/* Driver stuff */
|
/* Driver stuff */
|
||||||
#define DRIVERNAME "PostgreSQL ODBC"
|
#define DRIVERNAME "PostgreSQL ODBC"
|
||||||
#define DBMS_NAME "PostgreSQL"
|
#define DBMS_NAME "PostgreSQL"
|
||||||
#define DBMS_VERSION "06.30.0246 PostgreSQL 6.3"
|
#define DBMS_VERSION "06.30.0248 PostgreSQL 6.3"
|
||||||
#define POSTGRESDRIVERVERSION "06.30.0246"
|
#define POSTGRESDRIVERVERSION "06.30.0248"
|
||||||
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
|
|
||||||
|
|
||||||
|
#ifndef UNIX
|
||||||
|
#define DRIVER_FILE_NAME "PSQLODBC.DLL"
|
||||||
|
#else
|
||||||
|
#define DRIVER_FILE_NAME "libpsqlodbc.so"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PG62 "6.2" /* "Protocol" key setting to force Postgres 6.2 */
|
#define PG62 "6.2" /* "Protocol" key setting to force Postgres 6.2 */
|
||||||
|
|
||||||
@ -70,6 +91,7 @@ typedef struct EnvironmentClass_ EnvironmentClass;
|
|||||||
typedef struct TupleNode_ TupleNode;
|
typedef struct TupleNode_ TupleNode;
|
||||||
typedef struct TupleField_ TupleField;
|
typedef struct TupleField_ TupleField;
|
||||||
|
|
||||||
|
typedef struct col_info COL_INFO;
|
||||||
typedef struct lo_arg LO_ARG;
|
typedef struct lo_arg LO_ARG;
|
||||||
|
|
||||||
typedef struct GlobalValues_
|
typedef struct GlobalValues_
|
||||||
@ -89,6 +111,7 @@ typedef struct GlobalValues_
|
|||||||
char unknowns_as_longvarchar;
|
char unknowns_as_longvarchar;
|
||||||
char bools_as_char;
|
char bools_as_char;
|
||||||
char lie;
|
char lie;
|
||||||
|
char parse;
|
||||||
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
|
char extra_systable_prefixes[MEDIUM_REGISTRY_LEN];
|
||||||
char conn_settings[LARGE_REGISTRY_LEN];
|
char conn_settings[LARGE_REGISTRY_LEN];
|
||||||
} GLOBAL_VALUES;
|
} GLOBAL_VALUES;
|
||||||
|
@ -74,7 +74,8 @@ BEGIN
|
|||||||
EDITTEXT IDC_PASSWORD,175,55,72,12,ES_PASSWORD | ES_AUTOHSCROLL
|
EDITTEXT IDC_PASSWORD,175,55,72,12,ES_PASSWORD | ES_AUTOHSCROLL
|
||||||
DEFPUSHBUTTON "OK",IDOK,25,90,40,14,WS_GROUP
|
DEFPUSHBUTTON "OK",IDOK,25,90,40,14,WS_GROUP
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,80,90,40,14
|
PUSHBUTTON "Cancel",IDCANCEL,80,90,40,14
|
||||||
GROUPBOX "Options (Advanced):",IDC_STATIC,140,74,140,35,BS_CENTER
|
GROUPBOX "Options (Advanced):",IDC_OPTIONS,140,74,140,35,
|
||||||
|
BS_CENTER
|
||||||
PUSHBUTTON "Driver",IDC_DRIVER,160,90,50,14
|
PUSHBUTTON "Driver",IDC_DRIVER,160,90,50,14
|
||||||
PUSHBUTTON "DataSource",IDC_DATASOURCE,220,90,50,14
|
PUSHBUTTON "DataSource",IDC_DATASOURCE,220,90,50,14
|
||||||
CTEXT "Please supply any missing information needed to connect.",
|
CTEXT "Please supply any missing information needed to connect.",
|
||||||
@ -96,6 +97,8 @@ BEGIN
|
|||||||
BS_AUTOCHECKBOX | WS_TABSTOP,140,25,80,10
|
BS_AUTOCHECKBOX | WS_TABSTOP,140,25,80,10
|
||||||
CONTROL "&Use Declare/Fetch",DRV_USEDECLAREFETCH,"Button",
|
CONTROL "&Use Declare/Fetch",DRV_USEDECLAREFETCH,"Button",
|
||||||
BS_AUTOCHECKBOX | WS_TABSTOP,15,40,80,10
|
BS_AUTOCHECKBOX | WS_TABSTOP,15,40,80,10
|
||||||
|
CONTROL "P&arse Statements",DRV_PARSE,"Button",BS_AUTOCHECKBOX |
|
||||||
|
WS_TABSTOP,140,40,80,10
|
||||||
GROUPBOX "Unknown Sizes",IDC_STATIC,10,55,175,25
|
GROUPBOX "Unknown Sizes",IDC_STATIC,10,55,175,25
|
||||||
CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON |
|
CONTROL "Maximum",DRV_UNKNOWN_MAX,"Button",BS_AUTORADIOBUTTON |
|
||||||
WS_GROUP | WS_TABSTOP,15,65,45,10
|
WS_GROUP | WS_TABSTOP,15,65,45,10
|
||||||
@ -200,8 +203,8 @@ END
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 6,30,2,46
|
FILEVERSION 6,30,2,48
|
||||||
PRODUCTVERSION 6,30,2,46
|
PRODUCTVERSION 6,30,2,48
|
||||||
FILEFLAGSMASK 0x3L
|
FILEFLAGSMASK 0x3L
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -219,12 +222,12 @@ BEGIN
|
|||||||
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
|
VALUE "Comments", "PostgreSQL ODBC driver for Windows 95\0"
|
||||||
VALUE "CompanyName", "Insight Distribution Systems\0"
|
VALUE "CompanyName", "Insight Distribution Systems\0"
|
||||||
VALUE "FileDescription", "PostgreSQL Driver\0"
|
VALUE "FileDescription", "PostgreSQL Driver\0"
|
||||||
VALUE "FileVersion", " 6.30.0246\0"
|
VALUE "FileVersion", " 6.30.0248\0"
|
||||||
VALUE "InternalName", "psqlodbc\0"
|
VALUE "InternalName", "psqlodbc\0"
|
||||||
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft<66> is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
|
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft<66> is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
|
||||||
VALUE "OriginalFilename", "psqlodbc.dll\0"
|
VALUE "OriginalFilename", "psqlodbc.dll\0"
|
||||||
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
|
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
|
||||||
VALUE "ProductVersion", " 6.30.0246\0"
|
VALUE "ProductVersion", " 6.30.0248\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -21,6 +21,14 @@
|
|||||||
#include "qresult.h"
|
#include "qresult.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (BOOL)1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (BOOL)0
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
@ -232,6 +240,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
|
|||||||
QR_set_message(self, "Error reading field information");
|
QR_set_message(self, "Error reading field information");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#define DS_SHOWSYSTEMTABLES 1051
|
#define DS_SHOWSYSTEMTABLES 1051
|
||||||
#define DRV_EXTRASYSTABLEPREFIXES 1051
|
#define DRV_EXTRASYSTABLEPREFIXES 1051
|
||||||
#define DS_ROWVERSIONING 1052
|
#define DS_ROWVERSIONING 1052
|
||||||
|
#define DRV_PARSE 1052
|
||||||
|
#define IDC_OPTIONS 1054
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
@ -53,7 +55,7 @@
|
|||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1054
|
#define _APS_NEXT_CONTROL_VALUE 1055
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
#include "dlg_specific.h"
|
#include "dlg_specific.h"
|
||||||
@ -27,11 +31,34 @@
|
|||||||
#include "pgtypes.h"
|
#include "pgtypes.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isqlext.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sqlext.h>
|
#include <sqlext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFetch(HSTMT hstmt)
|
||||||
|
{
|
||||||
|
return _SQLFetch(hstmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLGetData(
|
||||||
|
HSTMT hstmt,
|
||||||
|
UWORD icol,
|
||||||
|
SWORD fCType,
|
||||||
|
PTR rgbValue,
|
||||||
|
SDWORD cbValueMax,
|
||||||
|
SDWORD FAR *pcbValue)
|
||||||
|
{
|
||||||
|
|
||||||
|
return _SQLGetData(hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue);
|
||||||
|
}
|
||||||
|
|
||||||
RETCODE SQL_API SQLRowCount(
|
RETCODE SQL_API SQLRowCount(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
SDWORD FAR *pcrow)
|
SDWORD FAR *pcrow)
|
||||||
@ -93,6 +120,7 @@ RETCODE SQL_API SQLNumResultCols(
|
|||||||
char *func="SQLNumResultCols";
|
char *func="SQLNumResultCols";
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
QResultClass *result;
|
QResultClass *result;
|
||||||
|
char parse_ok;
|
||||||
|
|
||||||
if ( ! stmt) {
|
if ( ! stmt) {
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -101,26 +129,37 @@ QResultClass *result;
|
|||||||
|
|
||||||
SC_clear_error(stmt);
|
SC_clear_error(stmt);
|
||||||
|
|
||||||
/* CC: Now check for the "prepared, but not executed" situation, that enables us to
|
parse_ok = FALSE;
|
||||||
deal with "SQLPrepare -- SQLDescribeCol -- ... -- SQLExecute" situations.
|
if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) {
|
||||||
(AutoCAD 13 ASE/ASI just _loves_ that ;-) )
|
|
||||||
*/
|
|
||||||
mylog("**** SQLNumResultCols: calling SC_pre_execute\n");
|
|
||||||
|
|
||||||
SC_pre_execute(stmt);
|
if (stmt->parse_status == STMT_PARSE_NONE) {
|
||||||
|
mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt);
|
||||||
|
parse_statement(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
result = SC_get_Result(stmt);
|
if (stmt->parse_status != STMT_PARSE_FATAL) {
|
||||||
|
parse_ok = TRUE;
|
||||||
mylog("SQLNumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
|
*pccol = stmt->nfld;
|
||||||
if (( ! result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) {
|
mylog("PARSE: SQLNumResultCols: *pccol = %d\n", *pccol);
|
||||||
/* no query has been executed on this statement */
|
}
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
|
||||||
stmt->errormsg = "No query has been executed with that handle";
|
|
||||||
SC_log_error(func, "", stmt);
|
|
||||||
return SQL_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pccol = QR_NumResultCols(result);
|
if ( ! parse_ok) {
|
||||||
|
|
||||||
|
SC_pre_execute(stmt);
|
||||||
|
result = SC_get_Result(stmt);
|
||||||
|
|
||||||
|
mylog("SQLNumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
|
||||||
|
if (( ! result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) {
|
||||||
|
/* no query has been executed on this statement */
|
||||||
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
|
stmt->errormsg = "No query has been executed with that handle";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pccol = QR_NumResultCols(result);
|
||||||
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -128,6 +167,8 @@ QResultClass *result;
|
|||||||
|
|
||||||
// - - - - - - - - -
|
// - - - - - - - - -
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Return information about the database column the user wants
|
// Return information about the database column the user wants
|
||||||
// information about.
|
// information about.
|
||||||
RETCODE SQL_API SQLDescribeCol(
|
RETCODE SQL_API SQLDescribeCol(
|
||||||
@ -145,10 +186,11 @@ char *func="SQLDescribeCol";
|
|||||||
/* gets all the information about a specific column */
|
/* gets all the information about a specific column */
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
QResultClass *result;
|
QResultClass *result;
|
||||||
char *name;
|
char *col_name;
|
||||||
Int4 fieldtype;
|
Int4 fieldtype;
|
||||||
int p;
|
int precision;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
|
char parse_ok;
|
||||||
|
|
||||||
if ( ! stmt) {
|
if ( ! stmt) {
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -159,24 +201,6 @@ ConnInfo *ci;
|
|||||||
|
|
||||||
SC_clear_error(stmt);
|
SC_clear_error(stmt);
|
||||||
|
|
||||||
/* CC: Now check for the "prepared, but not executed" situation, that enables us to
|
|
||||||
deal with "SQLPrepare -- SQLDescribeCol -- ... -- SQLExecute" situations.
|
|
||||||
(AutoCAD 13 ASE/ASI just _loves_ that ;-) )
|
|
||||||
*/
|
|
||||||
|
|
||||||
SC_pre_execute(stmt);
|
|
||||||
|
|
||||||
|
|
||||||
result = SC_get_Result(stmt);
|
|
||||||
mylog("**** SQLDescribeCol: result = %u, stmt->status = %d, !finished=%d, !premature=%d\n", result, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
|
|
||||||
if ( (NULL == result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) {
|
|
||||||
/* no query has been executed on this statement */
|
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
|
||||||
stmt->errormsg = "No query has been assigned to this statement.";
|
|
||||||
SC_log_error(func, "", stmt);
|
|
||||||
return SQL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(icol < 1) {
|
if(icol < 1) {
|
||||||
// we do not support bookmarks
|
// we do not support bookmarks
|
||||||
stmt->errormsg = "Bookmarks are not currently supported.";
|
stmt->errormsg = "Bookmarks are not currently supported.";
|
||||||
@ -187,60 +211,106 @@ ConnInfo *ci;
|
|||||||
|
|
||||||
icol--; /* use zero based column numbers */
|
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;
|
||||||
|
stmt->errormsg = "Invalid column number in DescribeCol.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
mylog("DescribeCol: getting info for icol=%d\n", icol);
|
||||||
|
|
||||||
|
fieldtype = stmt->fi[icol]->type;
|
||||||
|
col_name = stmt->fi[icol]->name;
|
||||||
|
precision = stmt->fi[icol]->precision;
|
||||||
|
|
||||||
|
mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
|
||||||
|
if (fieldtype > 0)
|
||||||
|
parse_ok = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
SC_pre_execute(stmt);
|
||||||
|
|
||||||
|
result = SC_get_Result(stmt);
|
||||||
|
|
||||||
|
mylog("**** SQLDescribeCol: result = %u, stmt->status = %d, !finished=%d, !premature=%d\n", result, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
|
||||||
|
if ( (NULL == result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) {
|
||||||
|
/* no query has been executed on this statement */
|
||||||
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
|
stmt->errormsg = "No query has been assigned to this statement.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icol >= QR_NumResultCols(result)) {
|
||||||
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
|
stmt->errormsg = "Invalid column number in DescribeCol.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
col_name = QR_get_fieldname(result, icol);
|
||||||
|
fieldtype = QR_get_field_type(result, icol);
|
||||||
|
|
||||||
|
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); // atoi(ci->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);
|
||||||
|
|
||||||
if (cbColNameMax >= 1) {
|
if (cbColNameMax >= 1) {
|
||||||
name = QR_get_fieldname(result, icol);
|
if (pcbColName) {
|
||||||
mylog("describeCol: col %d fieldname = '%s'\n", icol, name);
|
if (col_name)
|
||||||
/* our indices start from 0 whereas ODBC defines indices starting from 1 */
|
*pcbColName = strlen(col_name);
|
||||||
if (NULL != pcbColName) {
|
else
|
||||||
// we want to get the total number of bytes in the column name
|
|
||||||
if (NULL == name)
|
|
||||||
*pcbColName = 0;
|
*pcbColName = 0;
|
||||||
else
|
|
||||||
*pcbColName = strlen(name);
|
|
||||||
}
|
}
|
||||||
if (NULL != szColName) {
|
if (szColName) {
|
||||||
// get the column name into the buffer if there is one
|
if (col_name)
|
||||||
if (NULL == name)
|
strncpy_null(szColName, col_name, cbColNameMax);
|
||||||
szColName[0] = '\0';
|
|
||||||
else
|
else
|
||||||
strncpy_null(szColName, name, cbColNameMax);
|
szColName[0] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldtype = QR_get_field_type(result, icol);
|
|
||||||
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
|
|
||||||
|
|
||||||
if (NULL != pfSqlType) {
|
if (pfSqlType) {
|
||||||
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
||||||
|
|
||||||
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != pcbColDef) {
|
if (pcbColDef) {
|
||||||
|
|
||||||
/* If type is BPCHAR, then precision is length of column because all
|
if ( precision < 0)
|
||||||
columns in the result set will be blank padded to the column length.
|
precision = 0; // "I dont know"
|
||||||
|
|
||||||
If type is VARCHAR or TEXT, then precision can not be accurately
|
*pcbColDef = precision;
|
||||||
determined. Possibilities are:
|
|
||||||
1. return 0 (I dont know -- seems to work ok with Borland)
|
|
||||||
2. return MAXIMUM PRECISION for that datatype (Borland bad!)
|
|
||||||
3. return longest column thus far (that would be the longest
|
|
||||||
strlen of any row in the tuple cache, which may not be a
|
|
||||||
good representation if the result set is more than one
|
|
||||||
tuple cache long.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
p = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); // atoi(ci->unknown_sizes)
|
|
||||||
if ( p < 0)
|
|
||||||
p = 0; // "I dont know"
|
|
||||||
|
|
||||||
*pcbColDef = p;
|
|
||||||
|
|
||||||
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != pibScale) {
|
if (pibScale) {
|
||||||
Int2 scale;
|
Int2 scale;
|
||||||
scale = pgtype_scale(stmt, fieldtype);
|
scale = pgtype_scale(stmt, fieldtype);
|
||||||
if(scale == -1) { scale = 0; }
|
if(scale == -1) { scale = 0; }
|
||||||
@ -249,8 +319,12 @@ ConnInfo *ci;
|
|||||||
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != pfNullable) {
|
if (pfNullable) {
|
||||||
*pfNullable = pgtype_nullable(stmt, fieldtype);
|
if (parse_ok)
|
||||||
|
*pfNullable = stmt->fi[icol]->nullable;
|
||||||
|
else
|
||||||
|
*pfNullable = pgtype_nullable(stmt, fieldtype);
|
||||||
|
|
||||||
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
|
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +348,9 @@ char *value;
|
|||||||
Int4 field_type;
|
Int4 field_type;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
int unknown_sizes;
|
int unknown_sizes;
|
||||||
|
int cols;
|
||||||
|
char parse_ok;
|
||||||
|
|
||||||
|
|
||||||
if( ! stmt) {
|
if( ! stmt) {
|
||||||
SC_log_error(func, "", NULL);
|
SC_log_error(func, "", NULL);
|
||||||
@ -282,21 +359,6 @@ int unknown_sizes;
|
|||||||
|
|
||||||
ci = &(stmt->hdbc->connInfo);
|
ci = &(stmt->hdbc->connInfo);
|
||||||
|
|
||||||
/* CC: Now check for the "prepared, but not executed" situation, that enables us to
|
|
||||||
deal with "SQLPrepare -- SQLDescribeCol -- ... -- SQLExecute" situations.
|
|
||||||
(AutoCAD 13 ASE/ASI just _loves_ that ;-) )
|
|
||||||
*/
|
|
||||||
SC_pre_execute(stmt);
|
|
||||||
|
|
||||||
mylog("**** SQLColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1);
|
|
||||||
|
|
||||||
if ( (NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) {
|
|
||||||
stmt->errormsg = "Can't get column attributes: no result found.";
|
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
|
||||||
SC_log_error(func, "", stmt);
|
|
||||||
return SQL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(icol < 1) {
|
if(icol < 1) {
|
||||||
// we do not support bookmarks
|
// we do not support bookmarks
|
||||||
stmt->errormsg = "Bookmarks are not currently supported.";
|
stmt->errormsg = "Bookmarks are not currently supported.";
|
||||||
@ -305,18 +367,65 @@ int unknown_sizes;
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
icol -= 1;
|
icol--;
|
||||||
field_type = QR_get_field_type(stmt->result, icol);
|
|
||||||
|
|
||||||
mylog("colAttr: col %d field_type = %d\n", icol, field_type);
|
|
||||||
|
|
||||||
unknown_sizes = globals.unknown_sizes; // atoi(ci->unknown_sizes);
|
unknown_sizes = globals.unknown_sizes; // atoi(ci->unknown_sizes);
|
||||||
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) // not appropriate for SQLColAttributes()
|
if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) // not appropriate for SQLColAttributes()
|
||||||
unknown_sizes = UNKNOWNS_AS_MAX;
|
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");
|
||||||
|
parse_statement(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
cols = stmt->nfld;
|
||||||
|
|
||||||
|
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) {
|
||||||
|
|
||||||
|
if (icol >= cols) {
|
||||||
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
|
stmt->errormsg = "Invalid column number in DescribeCol.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_type = stmt->fi[icol]->type;
|
||||||
|
if (field_type > 0)
|
||||||
|
parse_ok = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! parse_ok) {
|
||||||
|
SC_pre_execute(stmt);
|
||||||
|
|
||||||
|
mylog("**** SQLColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1);
|
||||||
|
|
||||||
|
if ( (NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) {
|
||||||
|
stmt->errormsg = "Can't get column attributes: no result found.";
|
||||||
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cols = QR_NumResultCols(stmt->result);
|
||||||
|
if (icol >= cols) {
|
||||||
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
|
stmt->errormsg = "Invalid column number in DescribeCol.";
|
||||||
|
SC_log_error(func, "", stmt);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_type = QR_get_field_type(stmt->result, icol);
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog("colAttr: col %d field_type = %d\n", icol, field_type);
|
||||||
|
|
||||||
switch(fDescType) {
|
switch(fDescType) {
|
||||||
case SQL_COLUMN_AUTO_INCREMENT:
|
case SQL_COLUMN_AUTO_INCREMENT:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_auto_increment(stmt, field_type);
|
*pfDesc = pgtype_auto_increment(stmt, field_type);
|
||||||
if (*pfDesc == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
if (*pfDesc == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
||||||
*pfDesc = FALSE;
|
*pfDesc = FALSE;
|
||||||
@ -325,18 +434,21 @@ int unknown_sizes;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_CASE_SENSITIVE:
|
case SQL_COLUMN_CASE_SENSITIVE:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = pgtype_case_sensitive(stmt, field_type);
|
*pfDesc = pgtype_case_sensitive(stmt, field_type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_COUNT:
|
case SQL_COLUMN_COUNT:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = QR_NumResultCols(stmt->result);
|
*pfDesc = cols;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_DISPLAY_SIZE:
|
case SQL_COLUMN_DISPLAY_SIZE:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
if (parse_ok)
|
||||||
|
*pfDesc = stmt->fi[icol]->display_size;
|
||||||
|
else
|
||||||
|
*pfDesc = pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("SQLColAttributes: col %d, display_size= %d\n", icol, *pfDesc);
|
mylog("SQLColAttributes: col %d, display_size= %d\n", icol, *pfDesc);
|
||||||
@ -344,68 +456,104 @@ int unknown_sizes;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_LABEL:
|
case SQL_COLUMN_LABEL:
|
||||||
|
if (parse_ok && stmt->fi[icol]->alias[0] != '\0') {
|
||||||
|
strncpy_null((char *)rgbDesc, stmt->fi[icol]->alias, cbDescMax);
|
||||||
|
if (pcbDesc)
|
||||||
|
*pcbDesc = strlen(stmt->fi[icol]->alias);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", rgbDesc);
|
||||||
|
} // otherwise same as column name
|
||||||
|
|
||||||
case SQL_COLUMN_NAME:
|
case SQL_COLUMN_NAME:
|
||||||
value = QR_get_fieldname(stmt->result, icol);
|
|
||||||
|
if (parse_ok)
|
||||||
|
value = stmt->fi[icol]->name;
|
||||||
|
else
|
||||||
|
value = QR_get_fieldname(stmt->result, icol);
|
||||||
|
|
||||||
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
||||||
|
|
||||||
if (NULL != pcbDesc)
|
if (pcbDesc)
|
||||||
*pcbDesc = strlen(value);
|
*pcbDesc = strlen(value);
|
||||||
|
|
||||||
|
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", rgbDesc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_LENGTH:
|
case SQL_COLUMN_LENGTH:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_length(stmt, field_type, icol, unknown_sizes);
|
if (parse_ok)
|
||||||
|
*pfDesc = stmt->fi[icol]->length;
|
||||||
|
else
|
||||||
|
*pfDesc = pgtype_length(stmt, field_type, icol, unknown_sizes);
|
||||||
}
|
}
|
||||||
mylog("SQLColAttributes: col %d, length = %d\n", icol, *pfDesc);
|
mylog("SQLColAttributes: col %d, length = %d\n", icol, *pfDesc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_MONEY:
|
case SQL_COLUMN_MONEY:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = pgtype_money(stmt, field_type);
|
*pfDesc = pgtype_money(stmt, field_type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_NULLABLE:
|
case SQL_COLUMN_NULLABLE:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_nullable(stmt, field_type);
|
if (parse_ok)
|
||||||
|
*pfDesc = stmt->fi[icol]->nullable;
|
||||||
|
else
|
||||||
|
*pfDesc = pgtype_nullable(stmt, field_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_OWNER_NAME:
|
case SQL_COLUMN_OWNER_NAME:
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
||||||
if (NULL != pcbDesc)
|
if (pcbDesc)
|
||||||
*pcbDesc = 0;
|
*pcbDesc = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_PRECISION:
|
case SQL_COLUMN_PRECISION:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_precision(stmt, field_type, icol, unknown_sizes);
|
if (parse_ok)
|
||||||
|
*pfDesc = stmt->fi[icol]->precision;
|
||||||
|
else
|
||||||
|
*pfDesc = pgtype_precision(stmt, field_type, icol, unknown_sizes);
|
||||||
}
|
}
|
||||||
mylog("SQLColAttributes: col %d, precision = %d\n", icol, *pfDesc);
|
mylog("SQLColAttributes: col %d, precision = %d\n", icol, *pfDesc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_QUALIFIER_NAME:
|
case SQL_COLUMN_QUALIFIER_NAME:
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
||||||
if (NULL != pcbDesc)
|
if (pcbDesc)
|
||||||
*pcbDesc = 0;
|
*pcbDesc = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_SCALE:
|
case SQL_COLUMN_SCALE:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = pgtype_scale(stmt, field_type);
|
*pfDesc = pgtype_scale(stmt, field_type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_SEARCHABLE:
|
case SQL_COLUMN_SEARCHABLE:
|
||||||
if (NULL != pfDesc)
|
if (pfDesc)
|
||||||
*pfDesc = pgtype_searchable(stmt, field_type);
|
*pfDesc = pgtype_searchable(stmt, field_type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TABLE_NAME:
|
case SQL_COLUMN_TABLE_NAME:
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
if (parse_ok && stmt->fi[icol]->ti) {
|
||||||
if (NULL != pcbDesc)
|
strncpy_null((char *)rgbDesc, stmt->fi[icol]->ti->name, cbDescMax);
|
||||||
*pcbDesc = 0;
|
if (pcbDesc)
|
||||||
|
*pcbDesc = strlen(stmt->fi[icol]->ti->name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
||||||
|
if (pcbDesc)
|
||||||
|
*pcbDesc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog("SQLColAttr: TABLE_NAME = '%s'\n", rgbDesc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TYPE:
|
case SQL_COLUMN_TYPE:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_to_sqltype(stmt, field_type);
|
*pfDesc = pgtype_to_sqltype(stmt, field_type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -413,12 +561,12 @@ int unknown_sizes;
|
|||||||
case SQL_COLUMN_TYPE_NAME:
|
case SQL_COLUMN_TYPE_NAME:
|
||||||
value = pgtype_to_name(stmt, field_type);
|
value = pgtype_to_name(stmt, field_type);
|
||||||
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
||||||
if (NULL != pcbDesc)
|
if (pcbDesc)
|
||||||
*pcbDesc = strlen(value);
|
*pcbDesc = strlen(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_UNSIGNED:
|
case SQL_COLUMN_UNSIGNED:
|
||||||
if (NULL != pfDesc) {
|
if (pfDesc) {
|
||||||
*pfDesc = pgtype_unsigned(stmt, field_type);
|
*pfDesc = pgtype_unsigned(stmt, field_type);
|
||||||
if(*pfDesc == -1) /* non-numeric becomes TRUE (ODBC Doc) */
|
if(*pfDesc == -1) /* non-numeric becomes TRUE (ODBC Doc) */
|
||||||
*pfDesc = TRUE;
|
*pfDesc = TRUE;
|
||||||
@ -426,17 +574,16 @@ int unknown_sizes;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_UPDATABLE:
|
case SQL_COLUMN_UPDATABLE:
|
||||||
// everything should be updatable, I guess, unless access permissions
|
if (pfDesc) {
|
||||||
// prevent it--are we supposed to check for that here? seems kind
|
|
||||||
// of complicated. hmm...
|
|
||||||
if (NULL != pfDesc) {
|
|
||||||
/* Neither Access or Borland care about this.
|
/* Neither Access or Borland care about this.
|
||||||
|
|
||||||
if (field_type == PG_TYPE_OID)
|
if (field_type == PG_TYPE_OID)
|
||||||
*pfDesc = SQL_ATTR_READONLY;
|
*pfDesc = SQL_ATTR_READONLY;
|
||||||
else
|
else
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*pfDesc = SQL_ATTR_WRITE;
|
*pfDesc = SQL_ATTR_WRITE;
|
||||||
|
mylog("SQLColAttr: UPDATEABLE = %d\n", *pfDesc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -446,7 +593,7 @@ int unknown_sizes;
|
|||||||
|
|
||||||
// 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(
|
RETCODE SQL_API _SQLGetData(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
UWORD icol,
|
UWORD icol,
|
||||||
SWORD fCType,
|
SWORD fCType,
|
||||||
@ -590,7 +737,7 @@ mylog("SQLGetData: enter, stmt=%u\n", stmt);
|
|||||||
// Returns data for bound columns in the current row ("hstmt->iCursor"),
|
// Returns data for bound columns in the current row ("hstmt->iCursor"),
|
||||||
// advances the cursor.
|
// advances the cursor.
|
||||||
|
|
||||||
RETCODE SQL_API SQLFetch(
|
RETCODE SQL_API _SQLFetch(
|
||||||
HSTMT hstmt)
|
HSTMT hstmt)
|
||||||
{
|
{
|
||||||
char *func = "SQLFetch";
|
char *func = "SQLFetch";
|
||||||
@ -863,8 +1010,11 @@ RETCODE SQL_API SQLSetPos(
|
|||||||
UWORD fLock)
|
UWORD fLock)
|
||||||
{
|
{
|
||||||
char *func = "SQLSetPos";
|
char *func = "SQLSetPos";
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
|
sprintf(buf, "SQLSetPos not implemented: irow=%d, fOption=%d, fLock=%d\n", irow, fOption, fLock);
|
||||||
|
|
||||||
|
SC_log_error(func, buf, (StatementClass *) hstmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,10 +12,33 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h> /* for memset */
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
#ifndef BOOL
|
||||||
|
#define BOOL int
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (BOOL)1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (BOOL)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SOCK_clear_error(SocketClass *self)
|
SOCK_clear_error(SocketClass *self)
|
||||||
{
|
{
|
||||||
@ -31,7 +54,7 @@ SocketClass *rv;
|
|||||||
rv = (SocketClass *) malloc(sizeof(SocketClass));
|
rv = (SocketClass *) malloc(sizeof(SocketClass));
|
||||||
|
|
||||||
if (rv != NULL) {
|
if (rv != NULL) {
|
||||||
rv->socket = (SOCKET) -1;
|
rv->socket = (SOCKETFD) -1;
|
||||||
rv->buffer_filled_in = 0;
|
rv->buffer_filled_in = 0;
|
||||||
rv->buffer_filled_out = 0;
|
rv->buffer_filled_out = 0;
|
||||||
rv->buffer_read_in = 0;
|
rv->buffer_read_in = 0;
|
||||||
@ -119,7 +142,7 @@ unsigned long iaddr;
|
|||||||
self->errornumber = SOCKET_COULD_NOT_CONNECT;
|
self->errornumber = SOCKET_COULD_NOT_CONNECT;
|
||||||
self->errormsg = "Could not connect to remote socket.";
|
self->errormsg = "Could not connect to remote socket.";
|
||||||
closesocket(self->socket);
|
closesocket(self->socket);
|
||||||
self->socket = (SOCKET) -1;
|
self->socket = (SOCKETFD) -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -10,7 +10,23 @@
|
|||||||
#ifndef __SOCKET_H__
|
#ifndef __SOCKET_H__
|
||||||
#define __SOCKET_H__
|
#define __SOCKET_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#define closesocket(xxx) close(xxx)
|
||||||
|
#define SOCKETFD int
|
||||||
|
#else
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
|
#define SOCKETFD SOCKET
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
#define SOCKET_ALREADY_CONNECTED 1
|
#define SOCKET_ALREADY_CONNECTED 1
|
||||||
@ -33,7 +49,7 @@ struct SocketClass_ {
|
|||||||
unsigned char *buffer_in;
|
unsigned char *buffer_in;
|
||||||
unsigned char *buffer_out;
|
unsigned char *buffer_out;
|
||||||
|
|
||||||
SOCKET socket;
|
SOCKETFD socket;
|
||||||
|
|
||||||
char *errormsg;
|
char *errormsg;
|
||||||
int errornumber;
|
int errornumber;
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
#include "bind.h"
|
#include "bind.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
@ -19,12 +23,25 @@
|
|||||||
#include "convert.h"
|
#include "convert.h"
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern GLOBAL_VALUES globals;
|
extern GLOBAL_VALUES globals;
|
||||||
|
|
||||||
|
#ifdef UNIX
|
||||||
|
#if !HAVE_STRICMP
|
||||||
|
#define stricmp(s1,s2) strcasecmp(s1,s2)
|
||||||
|
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Map sql commands to statement types */
|
/* Map sql commands to statement types */
|
||||||
static struct {
|
static struct {
|
||||||
int type;
|
int type;
|
||||||
@ -45,6 +62,19 @@ static struct {
|
|||||||
|
|
||||||
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
|
RETCODE SQL_API SQLAllocStmt(HDBC hdbc,
|
||||||
HSTMT FAR *phstmt)
|
HSTMT FAR *phstmt)
|
||||||
|
{
|
||||||
|
return _SQLAllocStmt(hdbc, phstmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
|
||||||
|
UWORD fOption)
|
||||||
|
{
|
||||||
|
return _SQLFreeStmt(hstmt, fOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RETCODE SQL_API _SQLAllocStmt(HDBC hdbc,
|
||||||
|
HSTMT FAR *phstmt)
|
||||||
{
|
{
|
||||||
char *func="SQLAllocStmt";
|
char *func="SQLAllocStmt";
|
||||||
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
||||||
@ -82,7 +112,7 @@ StatementClass *stmt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API SQLFreeStmt(HSTMT hstmt,
|
RETCODE SQL_API _SQLFreeStmt(HSTMT hstmt,
|
||||||
UWORD fOption)
|
UWORD fOption)
|
||||||
{
|
{
|
||||||
char *func="SQLFreeStmt";
|
char *func="SQLFreeStmt";
|
||||||
@ -145,6 +175,7 @@ StatementClass *stmt = (StatementClass *) hstmt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* StatementClass implementation
|
* StatementClass implementation
|
||||||
*/
|
*/
|
||||||
@ -185,6 +216,12 @@ StatementClass *rv;
|
|||||||
rv->lobj_fd = -1;
|
rv->lobj_fd = -1;
|
||||||
rv->internal = FALSE;
|
rv->internal = FALSE;
|
||||||
rv->cursor_name[0] = '\0';
|
rv->cursor_name[0] = '\0';
|
||||||
|
|
||||||
|
rv->ti = NULL;
|
||||||
|
rv->fi = NULL;
|
||||||
|
rv->ntab = 0;
|
||||||
|
rv->nfld = 0;
|
||||||
|
rv->parse_status = STMT_PARSE_NONE;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -218,6 +255,27 @@ SC_Destructor(StatementClass *self)
|
|||||||
if (self->bindings)
|
if (self->bindings)
|
||||||
free(self->bindings);
|
free(self->bindings);
|
||||||
|
|
||||||
|
|
||||||
|
/* Free the parsed table information */
|
||||||
|
if (self->ti) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < self->ntab; i++) {
|
||||||
|
free(self->ti[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the parsed field information */
|
||||||
|
if (self->fi) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < self->nfld; i++) {
|
||||||
|
free(self->fi[i]);
|
||||||
|
}
|
||||||
|
free(self->fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
free(self);
|
free(self);
|
||||||
|
|
||||||
mylog("SC_Destructor: EXIT\n");
|
mylog("SC_Destructor: EXIT\n");
|
||||||
@ -266,7 +324,6 @@ int i;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
statement_type(char *statement)
|
statement_type(char *statement)
|
||||||
{
|
{
|
||||||
@ -279,6 +336,7 @@ int i;
|
|||||||
return STMT_TYPE_OTHER;
|
return STMT_TYPE_OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Called from SQLPrepare if STMT_PREMATURE, or
|
/* Called from SQLPrepare if STMT_PREMATURE, or
|
||||||
from SQLExecute if STMT_FINISHED, or
|
from SQLExecute if STMT_FINISHED, or
|
||||||
from SQLFreeStmt(SQL_CLOSE)
|
from SQLFreeStmt(SQL_CLOSE)
|
||||||
@ -328,6 +386,29 @@ ConnectionClass *conn;
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the parsed table information */
|
||||||
|
if (self->ti) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < self->ntab; i++) {
|
||||||
|
free(self->ti[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->ti);
|
||||||
|
self->ti = NULL;
|
||||||
|
self->ntab = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the parsed field information */
|
||||||
|
if (self->fi) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < self->nfld; i++) {
|
||||||
|
free(self->fi[i]);
|
||||||
|
}
|
||||||
|
free(self->fi);
|
||||||
|
self->fi = NULL;
|
||||||
|
self->nfld = 0;
|
||||||
|
}
|
||||||
|
self->parse_status = STMT_PARSE_NONE;
|
||||||
|
|
||||||
/* Free any cursors */
|
/* Free any cursors */
|
||||||
if (self->result) {
|
if (self->result) {
|
||||||
@ -359,7 +440,7 @@ ConnectionClass *conn;
|
|||||||
void
|
void
|
||||||
SC_pre_execute(StatementClass *self)
|
SC_pre_execute(StatementClass *self)
|
||||||
{
|
{
|
||||||
|
|
||||||
mylog("SC_pre_execute: status = %d\n", self->status);
|
mylog("SC_pre_execute: status = %d\n", self->status);
|
||||||
|
|
||||||
if (self->status == STMT_READY) {
|
if (self->status == STMT_READY) {
|
||||||
@ -515,6 +596,7 @@ Int2 oldstatus, numcols;
|
|||||||
|
|
||||||
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
|
||||||
|
|
||||||
|
|
||||||
/* send the declare/select */
|
/* send the declare/select */
|
||||||
self->result = CC_send_query(conn, self->stmt_with_params, NULL, NULL);
|
self->result = CC_send_query(conn, self->stmt_with_params, NULL, NULL);
|
||||||
|
|
||||||
|
@ -10,10 +10,27 @@
|
|||||||
#ifndef __STATEMENT_H__
|
#ifndef __STATEMENT_H__
|
||||||
#define __STATEMENT_H__
|
#define __STATEMENT_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IODBC
|
||||||
|
#include "iodbc.h"
|
||||||
|
#include "isql.h"
|
||||||
|
#else
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "psqlodbc.h"
|
#include "psqlodbc.h"
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE (BOOL)0
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE (BOOL)1
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STMT_ALLOCATED, /* The statement handle is allocated, but not used so far */
|
STMT_ALLOCATED, /* The statement handle is allocated, but not used so far */
|
||||||
STMT_READY, /* the statement is waiting to be executed */
|
STMT_READY, /* the statement is waiting to be executed */
|
||||||
@ -66,6 +83,40 @@ enum {
|
|||||||
|
|
||||||
#define STMT_UPDATE(stmt) (stmt->statement_type > STMT_TYPE_SELECT)
|
#define STMT_UPDATE(stmt) (stmt->statement_type > STMT_TYPE_SELECT)
|
||||||
|
|
||||||
|
|
||||||
|
/* Parsing status */
|
||||||
|
enum {
|
||||||
|
STMT_PARSE_NONE = 0,
|
||||||
|
STMT_PARSE_COMPLETE,
|
||||||
|
STMT_PARSE_INCOMPLETE,
|
||||||
|
STMT_PARSE_FATAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
COL_INFO *col_info; /* cached SQLColumns info for this table */
|
||||||
|
char name[MAX_TABLE_LEN+1];
|
||||||
|
char alias[MAX_TABLE_LEN+1];
|
||||||
|
} TABLE_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TABLE_INFO *ti; /* resolve to explicit table names */
|
||||||
|
int precision;
|
||||||
|
int display_size;
|
||||||
|
int length;
|
||||||
|
int type;
|
||||||
|
char nullable;
|
||||||
|
char func;
|
||||||
|
char expr;
|
||||||
|
char quote;
|
||||||
|
char dquote;
|
||||||
|
char numeric;
|
||||||
|
char dot[MAX_TABLE_LEN+1];
|
||||||
|
char name[MAX_COLUMN_LEN+1];
|
||||||
|
char alias[MAX_COLUMN_LEN+1];
|
||||||
|
} FIELD_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******** Statement Handle ***********/
|
/******** Statement Handle ***********/
|
||||||
struct StatementClass_ {
|
struct StatementClass_ {
|
||||||
ConnectionClass *hdbc; /* pointer to ConnectionClass this statement belongs to */
|
ConnectionClass *hdbc; /* pointer to ConnectionClass this statement belongs to */
|
||||||
@ -95,6 +146,13 @@ struct StatementClass_ {
|
|||||||
|
|
||||||
char *statement; /* if non--null pointer to the SQL statement that has been executed */
|
char *statement; /* if non--null pointer to the SQL statement that has been executed */
|
||||||
|
|
||||||
|
TABLE_INFO **ti;
|
||||||
|
FIELD_INFO **fi;
|
||||||
|
int nfld;
|
||||||
|
int ntab;
|
||||||
|
|
||||||
|
int parse_status;
|
||||||
|
|
||||||
int statement_type; /* According to the defines above */
|
int statement_type; /* According to the defines above */
|
||||||
int data_at_exec; /* Number of params needing SQLPutData */
|
int data_at_exec; /* Number of params needing SQLPutData */
|
||||||
int current_exec_param; /* The current parameter for SQLPutData */
|
int current_exec_param; /* The current parameter for SQLPutData */
|
||||||
@ -107,7 +165,8 @@ struct StatementClass_ {
|
|||||||
|
|
||||||
char internal; /* Is this statement being called internally? */
|
char internal; /* Is this statement being called internally? */
|
||||||
|
|
||||||
char cursor_name[32];
|
char cursor_name[MAX_CURSOR_LEN+1];
|
||||||
|
|
||||||
char stmt_with_params[65536 /* MAX_STATEMENT_LEN */]; /* statement after parameter substitution */
|
char stmt_with_params[65536 /* MAX_STATEMENT_LEN */]; /* statement after parameter substitution */
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -123,6 +182,7 @@ struct StatementClass_ {
|
|||||||
StatementClass *SC_Constructor();
|
StatementClass *SC_Constructor();
|
||||||
char SC_Destructor(StatementClass *self);
|
char SC_Destructor(StatementClass *self);
|
||||||
int statement_type(char *statement);
|
int statement_type(char *statement);
|
||||||
|
char parse_statement(StatementClass *stmt);
|
||||||
void SC_pre_execute(StatementClass *self);
|
void SC_pre_execute(StatementClass *self);
|
||||||
char SC_unbind_cols(StatementClass *self);
|
char SC_unbind_cols(StatementClass *self);
|
||||||
char SC_recycle_statement(StatementClass *self);
|
char SC_recycle_statement(StatementClass *self);
|
||||||
@ -134,4 +194,16 @@ RETCODE SC_execute(StatementClass *stmt);
|
|||||||
void SC_free_params(StatementClass *self, char option);
|
void SC_free_params(StatementClass *self, char option);
|
||||||
void SC_log_error(char *func, char *desc, StatementClass *self);
|
void SC_log_error(char *func, char *desc, StatementClass *self);
|
||||||
|
|
||||||
|
RETCODE SQL_API _SQLAllocStmt(HDBC hdbc, HSTMT FAR *phstmt);
|
||||||
|
RETCODE SQL_API _SQLFreeStmt(HSTMT hstmt, UWORD fOption);
|
||||||
|
RETCODE SQL_API _SQLExecDirect(HSTMT hstmt, UCHAR FAR *szSqlStr, SDWORD cbSqlStr);
|
||||||
|
RETCODE SQL_API _SQLFetch(HSTMT hstmt);
|
||||||
|
RETCODE SQL_API _SQLGetData(
|
||||||
|
HSTMT hstmt,
|
||||||
|
UWORD icol,
|
||||||
|
SWORD fCType,
|
||||||
|
PTR rgbValue,
|
||||||
|
SDWORD cbValueMax,
|
||||||
|
SDWORD FAR *pcbValue);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user