diff --git a/Builds/Gcc.lin/makefile.linux b/Builds/Gcc.lin/makefile.linux index 2eaf897d..ef2c5f93 100644 --- a/Builds/Gcc.lin/makefile.linux +++ b/Builds/Gcc.lin/makefile.linux @@ -91,11 +91,11 @@ LIST_ODBCJDBCOBJ = $(addprefix $(BUILDDIR)/, $(ODBCJDBCSRC:.cpp=.o)) LIST_ODBCJDBCSETUPSRC = $(addprefix $(ODBCJDBCDIR)/, $(ODBCJDBCSETUPSRC_LINUX)) LIST_ODBCJDBCSETUPOBJ = $(addprefix $(BUILDDIR)/, $(ODBCJDBCSETUPSRC_LINUX:.cpp=.o)) # -COMPFLAGS = -w -D_REENTRANT -D_PTHREADS -DEXTERNAL -D$(ODBCMANAGER) $(INCLUDEDIR) -I$(FBINCDIR) +COMPFLAGS = -w -D_REENTRANT -D_PTHREADS -DEXTERNAL -D$(ODBCMANAGER) $(INCLUDEDIR) -I$(FBINCDIR) --std=c++17 $(CXXFLAGS) -MMD ifeq ($(ARCH),x86_64) COMPFLAGS += -fPIC -m64 -LINKFLAGS= -shared -m64 +LINKFLAGS= -shared -m64 -Wl,--no-undefined else ifeq ($(ARCH),aarch64) COMPFLAGS += -fPIC LINKFLAGS= -shared @@ -104,7 +104,7 @@ COMPFLAGS += -m32 LINKFLAGS= -shared -m32 endif # -#LINKFLAGS = -rdynamic -export-dynamic -shared +#LINKFLAGS = -rdynamic -export-dynamic -shared EXTLIBS = $(EXTLIBDIR) -lcrypt -ldl @@ -140,7 +140,7 @@ ODBCJDBCSETUPLIB= $(ODBCJDBCSETUPDLL:.so=.a) all : createdirs $(ISCDBCDLL) $(ODBCJDBCDLL) $(ODBCJDBCSETUPDLL) # # If required, print out the version info -getVersion : +getVersion : $(warning MAJOR_VERSION is $(MAJOR_VERSION) ) $(warning MINOR_VERSION is $(MINOR_VERSION) ) $(warning REVISION is $(REVISION) ) @@ -173,10 +173,10 @@ $(ODBCJDBCSETUPDLL) : $(LIST_ODBCJDBCSETUPOBJ) # ar crs $(ODBCJDBCSETUPLIB) $(LIST_ODBCJDBCSETUPOBJ) # $(GCC) $(LINKFLAGS) $(LIST_ODBCJDBCSETUPOBJ) $(EXTLIBS) -o $(ODBCJDBCSETUPDLL) # -$(ODBCJDBCDLL) : $(ISCDBCDLL) $(ODBCJDBCSETUPDLL) $(LIST_ODBCJDBCOBJ) - ar crs $(ODBCJDBCLIB) $(LIST_ISCDBCOBJ) - ar crs $(ODBCJDBCLIB) $(LIST_ODBCJDBCOBJ) - ar crs $(ODBCJDBCLIB) $(LIST_ODBCJDBCSETUPOBJ) +$(ODBCJDBCDLL) : $(LIST_ISCDBCOBJ) $(LIST_ODBCJDBCSETUPOBJ) $(LIST_ODBCJDBCOBJ) +# ar crs $(ODBCJDBCLIB) $(LIST_ISCDBCOBJ) +# ar crs $(ODBCJDBCLIB) $(LIST_ODBCJDBCOBJ) +# ar crs $(ODBCJDBCLIB) $(LIST_ODBCJDBCSETUPOBJ) $(GCC) $(LINKFLAGS) $(LIST_ISCDBCOBJ) $(LIST_ODBCJDBCOBJ) $(LIST_ODBCJDBCSETUPOBJ) $(EXTLIBS) $(LIBODBCINST) -o $(ODBCJDBCDLL) # postbuild : $(ISCDBCDLL) $(ODBCJDBCDLL) $(ODBCJDBCSETUPDLL) @@ -184,28 +184,30 @@ postbuild : $(ISCDBCDLL) $(ODBCJDBCDLL) $(ODBCJDBCSETUPDLL) @-tar -cf OdbcJdbc_Snapshot.tar $(ISCDBCDLL) $(ODBCJDBCDLL) $(ODBCJDBCSETUPDLL) @-gzip -9 -S .gz OdbcJdbc_Snapshot.tar # -install : +install : cp $(ODBCJDBCDLL) $(UNIXODBCDIR)/$(ODBCJDBC).$(LIB_VERSION) ln -s $(UNIXODBCDIR)/$(ODBCJDBC).$(LIB_VERSION) $(UNIXODBCDIR)/$(ODBCJDBC) ln -s $(UNIXODBCDIR)/$(ODBCJDBC).$(LIB_VERSION) $(UNIXODBCDIR)/$(ODBCJDBC).$(MAJOR_VERSION) # -uninstall : - @-rm -f $(UNIXODBCDIR)/$(ODBCJDBC)*.* +uninstall : + @-rm -f $(UNIXODBCDIR)/$(ODBCJDBC)*.* # package : -strip -s $(ISCDBCDLL) $(ODBCJDBCDLL) $(ODBCJDBCSETUPDLL) -rm $(PACKAGE_NAME).gz chmod 740 ../../Install/Linux/install.sh tar -C $(TARGETDIR) -cvf OdbcJdbcLibs.tar $(ISCDBC) $(ODBCJDBC) $(ODBCJDBCSETUP) - tar -C ../../Install/HtmlHelp --exclude=CVS -cvf OdbcJdbcDocs.tar html/ + tar -C ../../Install/HtmlHelp --exclude=CVS -cvf OdbcJdbcDocs.tar html/ tar -C ../../Install -uf OdbcJdbcDocs.tar ReleaseNotes_v2.0.html cat $(DRVTMPL) | grep -v "^Driver.*=.*" >$(DRVTMPL).tmp && echo "Driver = $(UNIXODBCDIR)/$(ODBCJDBC)" >>$(DRVTMPL).tmp && mv $(DRVTMPL).tmp $(DRVTMPL) tar -C ../../Install/Linux -cf $(PACKAGE_NAME) install.sh readme.txt DriverTemplate.ini FirebirdDSNTemplate.ini InterBaseDSNTemplate.ini tar -uf $(PACKAGE_NAME) OdbcJdbcLibs.tar OdbcJdbcDocs.tar rm OdbcJdbcLibs.tar OdbcJdbcDocs.tar - gzip -9 -S .gz $(PACKAGE_NAME) + gzip -9 -S .gz $(PACKAGE_NAME) # +-include $(BUILDDIR)/*.d + # # End # diff --git a/DescRecord.cpp b/DescRecord.cpp index 46251526..e2bb2c80 100644 --- a/DescRecord.cpp +++ b/DescRecord.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -78,13 +78,6 @@ DescRecord::DescRecord() unNamed = SQL_NAMED; dataPtr = NULL; fnConv = NULL; -#ifdef _WINDOWS - WcsToMbs = _WcsToMbs; - MbsToWcs = _MbsToWcs; -#else - WcsToMbs = wcstombs; - MbsToWcs = mbstowcs; -#endif } DescRecord::~DescRecord() @@ -173,7 +166,7 @@ bool DescRecord::operator =(DescRecord *rec) unSigned = rec->unSigned; updaTable = rec->updaTable; indicatorPtr = rec->indicatorPtr; - + if ( indicatorPtr && !octetLengthPtr ) octetLengthPtr = indicatorPtr; diff --git a/DescRecord.h b/DescRecord.h index c729a2b3..e5be0edd 100644 --- a/DescRecord.h +++ b/DescRecord.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -45,10 +45,10 @@ class DescRecord void freeLocalDataPtr(); void beginBlobDataTransfer(); void putBlobSegmentData (int length, const void *bytes); - void endBlobDataTransfer(); + void endBlobDataTransfer(); int getBufferLength() - { + { return ( octetLength + 1 ) * headSqlVarPtr->getSqlMultiple(); } @@ -58,7 +58,7 @@ class DescRecord bool isIndicatorSqlDa; bool isZeroColumn; bool isLocalDataPtr; // use sqlPutData for set data_at_exec - char *localDataPtr; + char *localDataPtr; SQLSMALLINT callType; // use sqlGetData int isBlobOrArray; @@ -69,7 +69,7 @@ class DescRecord int currentFetched; bool startedReturnSQLData; HeadSqlVar *headSqlVarPtr; - Blob *dataBlobPtr; // for blob or array + Blob *dataBlobPtr; // for blob or array SQLSMALLINT type; SQLSMALLINT datetimeIntervalCode; @@ -104,8 +104,6 @@ class DescRecord SQLLEN *indicatorPtr; SQLSMALLINT unNamed; SQLPOINTER dataPtr; - WCSTOMBS WcsToMbs; - MBSTOWCS MbsToWcs; public: diff --git a/IscDbc/Attachment.cpp b/IscDbc/Attachment.cpp index fe549e1c..9a2e62ca 100644 --- a/IscDbc/Attachment.cpp +++ b/IscDbc/Attachment.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -37,17 +37,18 @@ #include "SQLError.h" #include "Parameters.h" #include "IscConnection.h" +#include "MultibyteConvert.h" -static char databaseInfoItems [] = { +static char databaseInfoItems [] = { isc_info_db_id, isc_info_db_sql_dialect, isc_info_base_level, isc_info_ods_version, isc_info_firebird_version, - isc_info_version, + isc_info_version, isc_info_page_size, isc_info_user_names, - isc_info_end + isc_info_end }; using namespace Firebird; @@ -167,7 +168,7 @@ void Attachment::createDatabase(const char *dbName, Properties *properties) p += sprintf( p, "DEFAULT CHARACTER SET %s ", charset ); *p = '\0'; - + ThrowStatusWrapper status( GDS->_status ); try { @@ -259,6 +260,11 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) charsetCode = findCharsetsCode( charset ); } + if (charsetCode == Charset::Code::Utf8) + { + dpb->insertTag(&throw_status, isc_dpb_utf8_filename); + } + const char *property = properties->findValue ("databaseAccess", NULL); if ( property ) @@ -313,7 +319,7 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) else { JString text; - + switch ( statusVector [7] ) { case isc_io_access_err: @@ -376,7 +382,7 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) case isc_info_db_sql_dialect: databaseDialect = GDS->_vax_integer (p, length); break; - + case isc_info_base_level: serverBaseLevel = GDS->_vax_integer (p, length); break; @@ -396,7 +402,7 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) char * start = p + 2; char * beg = start; char * end = beg + p [1]; - + while ( beg < end ) { if ( *beg >= '0' && *beg <= '9' ) @@ -437,7 +443,7 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) char * beg = start; char * end = beg + p [1]; char * tmp = NULL; - + while ( beg < end ) { if ( *beg >= '0' && *beg <= '9' ) @@ -488,7 +494,7 @@ void Attachment::openDatabase(const char *dbName, Properties *properties) p += length; } } - + if ( dialect && *dialect == '1') databaseDialect = SQL_DIALECT_V5; else diff --git a/IscDbc/BinaryBlob.cpp b/IscDbc/BinaryBlob.cpp index f0e3177f..5dee6dbe 100644 --- a/IscDbc/BinaryBlob.cpp +++ b/IscDbc/BinaryBlob.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -22,7 +22,7 @@ * * 2002-05-21 BinaryBlob.cpp * Change release() to test useCount <=0 - * + * * 2002-05-20 BinaryBlob.cpp * Contributed by Robert Milharcic * o Start with useCount of 0 diff --git a/IscDbc/BinaryBlob.h b/IscDbc/BinaryBlob.h index 9b748d22..0a5462aa 100644 --- a/IscDbc/BinaryBlob.h +++ b/IscDbc/BinaryBlob.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -37,7 +37,7 @@ namespace IscDbcLibrary { class Database; -class BinaryBlob : public Blob, public Stream +class BinaryBlob : public Blob, public Stream { public: void putSegment (Blob *blob); @@ -81,6 +81,7 @@ class BinaryBlob : public Blob, public Stream int sectionId; int recordNumber; bool populated; + bool directBlob; int directLength; }; diff --git a/IscDbc/Connection.h b/IscDbc/Connection.h index d00192cd..e5ce3b0f 100644 --- a/IscDbc/Connection.h +++ b/IscDbc/Connection.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -21,7 +21,7 @@ * 2002-06-25 Connection.h * Contributed by C. G. Alvarez * declare getDatabaseServerName() in DatabaseMetaData - * + * * * 2002-06-04 Connection.h * Contributed by Robert Milharcic @@ -73,9 +73,6 @@ typedef unsigned __int64 UQUAD; #define GET_ENTRY_POINT(libraryHandle,nameProc) GetProcAddress( libraryHandle, nameProc ) #define CLOSE_SHARE_LIBLARY(libraryHandle) FreeLibrary( libraryHandle ) -size_t _MbsToWcs( wchar_t *wcstr, const char *mbstr, size_t count ); -size_t _WcsToMbs( char *mbstr, const wchar_t *wcstr, size_t count ); - #elif defined (__APPLE__) #define NAME_CLIENT_SHARE_LIBRARY "libgds.dylib" @@ -103,7 +100,7 @@ size_t _WcsToMbs( char *mbstr, const wchar_t *wcstr, size_t count ); #endif // ISC_TIME_SECONDS_PRECISION -// Default standart size of fraction it's 9 number +// Default standart size of fraction it's 9 number // It's 9 = ISC_TIME_SECONDS_PRECISION * STD_TIME_SECONDS_PRECISION #define STD_TIME_SECONDS_PRECISION 100000L @@ -128,8 +125,6 @@ enum tra_flags_vals { }; typedef void (*callbackEvent)( void *interfaseUserEvents, short length, char *updated ); -typedef size_t (*WCSTOMBS)( char *mbstr, const wchar_t *wcstr, size_t count ); -typedef size_t (*MBSTOWCS)( wchar_t *wcstr, const char *mbstr, size_t count ); namespace IscDbcLibrary { @@ -195,7 +190,7 @@ class EnvironmentShare virtual void sqlEndTran(int operation) = 0; }; -class Connection +class Connection { public: //{{{ specification jdbc @@ -250,8 +245,6 @@ class Connection virtual int getUseAppOdbcVersion () = 0; virtual void setUseAppOdbcVersion ( int appOdbcVersion ) = 0; virtual int getConnectionCharsetCode() = 0; - virtual WCSTOMBS getConnectionWcsToMbs() = 0; - virtual MBSTOWCS getConnectionMbsToWcs() = 0; virtual void addRef() = 0; virtual int release() = 0; @@ -261,7 +254,7 @@ class Connection #define DATABASEMETADATA_VERSION 1 -class DatabaseMetaData +class DatabaseMetaData { public: //{{{ specification jdbc @@ -455,7 +448,7 @@ class Driver #define STATEMENT_VERSION 1 -class Statement +class Statement { public: //{{{ specification jdbc @@ -538,7 +531,7 @@ class HeadSqlVar #define STATEMENTMETADATA_VERSION 1 -class StatementMetaData +class StatementMetaData { public: // specification jdbc @@ -571,17 +564,15 @@ class StatementMetaData public: virtual void getSqlData(int index, Blob *& ptDataBlob, HeadSqlVar *& ptHeadSqlVar) = 0; virtual void createBlobDataTransfer(int index, Blob *& ptDataBlob) = 0; - virtual WCSTOMBS getAdressWcsToMbs( int index ) = 0; - virtual MBSTOWCS getAdressMbsToWcs( int index ) = 0; virtual int objectVersion() = 0; }; #define PREPAREDSTATEMENT_VERSION 1 -class PreparedStatement : public Statement +class PreparedStatement : public Statement { -public: +public: //{{{ specification jdbc virtual void clearParameters() = 0; virtual bool execute() = 0; @@ -627,7 +618,7 @@ class PreparedStatement : public Statement #define RESULTSET_VERSION 1 -class ResultSet +class ResultSet { public: //{{{ specification jdbc @@ -756,7 +747,7 @@ class ResultSet #define RESULTSETMETADATA_VERSION 1 -class ResultSetMetaData +class ResultSetMetaData { public: virtual const char* getTableName (int index) = 0; @@ -785,7 +776,7 @@ class ResultSetMetaData #define RESULTLIST_VERSION 1 -class ResultList +class ResultList { public: virtual const char* getTableName() = 0; @@ -840,9 +831,9 @@ class InternalStatement : public Statement virtual bool executeProcedure() = 0; virtual void rollbackLocal() = 0; virtual void commitLocal() = 0; - virtual StatementMetaData* + virtual StatementMetaData* getStatementMetaDataIPD() = 0; - virtual StatementMetaData* + virtual StatementMetaData* getStatementMetaDataIRD() = 0; virtual int getNumParams() = 0; virtual void drop() = 0; diff --git a/IscDbc/IscBlob.h b/IscDbc/IscBlob.h index 3589b63c..4e7d2b35 100644 --- a/IscDbc/IscBlob.h +++ b/IscDbc/IscBlob.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -66,7 +66,6 @@ class IscBlob : public BinaryBlob ISC_QUAD blobId; Firebird::IBlob* directBlobHandle; bool fetched; - bool directBlob; }; }; // end namespace IscDbcLibrary diff --git a/IscDbc/IscConnection.cpp b/IscDbc/IscConnection.cpp index 1a09c32f..6e3e0594 100644 --- a/IscDbc/IscConnection.cpp +++ b/IscDbc/IscConnection.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -22,7 +22,7 @@ * * 2003-03-24 IscConnection.cpp * Contributed by Norbert Meyer - * o If ++attachment means attachment->addRef() + * o If ++attachment means attachment->addRef() * then let's say so. * o In close() set statement->connection to NULL. * This prevents connection->deleteStatement(this) @@ -34,7 +34,7 @@ * to better support different transaction options. * * 2002-05-20 IscConnection.cpp - * + * * Contributed by Robert Milharcic * o better management of statements variable * @@ -81,7 +81,8 @@ extern EnvShare environmentShare; extern "C" Connection* createConnection() { - setlocale( LC_ALL, ".ACP" ); + // Library must not mess with locale, it can drive applications crazy. + //setlocale( LC_ALL, ".ACP" ); return new IscConnection; } @@ -267,7 +268,7 @@ bool IscConnection::getTransactionPending() } Firebird::IAttachment* IscConnection::getHandleDb() -{ +{ return attachment->databaseHandle; } @@ -521,7 +522,7 @@ int IscConnection::buildParamProcedure ( char *& string, int numInputParam ) memmove(ptSrc, ptCh, strlen(ptCh) + 1 ); string = ptSrc + 1; - return 1; + return 1; } SKIP_WHITE(ptSrc); @@ -554,9 +555,9 @@ bool IscConnection::paramTransactionModes( char *& string, short &transFlags, bo { char *& ptOut = string; - if ( IS_MATCH_EXT( "READ" ) ) + if ( IS_MATCH_EXT( "READ" ) ) { - if ( IS_MATCH_EXT( "ONLY" ) ) + if ( IS_MATCH_EXT( "ONLY" ) ) { if ( expectIsolation ) throw SQLEXCEPTION( SYNTAX_ERROR, "after SNAPSHOT not ONLY" ); @@ -564,7 +565,7 @@ bool IscConnection::paramTransactionModes( char *& string, short &transFlags, bo transFlags |= TRA_ro; return true; } - else if ( IS_MATCH_EXT( "WRITE" ) ) + else if ( IS_MATCH_EXT( "WRITE" ) ) { if ( expectIsolation ) throw SQLEXCEPTION( SYNTAX_ERROR, "after SNAPSHOT not WRITE" ); @@ -574,17 +575,17 @@ bool IscConnection::paramTransactionModes( char *& string, short &transFlags, bo if ( !( IS_MATCH_EXT( "COMMITTED" ) || IS_MATCH_EXT( "UNCOMMITTED" ) ) ) throw SQLEXCEPTION( SYNTAX_ERROR, "should be keyword COMMITTED or UNCOMMITTED" ); - + transFlags |= TRA_read_committed; - if ( IS_MATCH_EXT( "NO" ) ) + if ( IS_MATCH_EXT( "NO" ) ) { if ( IS_MATCH_EXT( "RECORD_VERSION" ) ) { transFlags |= TRA_no_rec_version; return true; } - else if ( IS_MATCH_EXT( "WAIT" ) ) + else if ( IS_MATCH_EXT( "WAIT" ) ) { transFlags |= TRA_nw; return true; @@ -596,9 +597,9 @@ bool IscConnection::paramTransactionModes( char *& string, short &transFlags, bo IS_MATCH_EXT( "RECORD_VERSION" ); return true; } - else if ( IS_MATCH_EXT( "SNAPSHOT" ) ) + else if ( IS_MATCH_EXT( "SNAPSHOT" ) ) { - if ( IS_MATCH_EXT( "TABLE" ) ) + if ( IS_MATCH_EXT( "TABLE" ) ) { transFlags |= TRA_con; @@ -608,7 +609,7 @@ bool IscConnection::paramTransactionModes( char *& string, short &transFlags, bo } else if ( IS_MATCH_EXT( "REPEATABLE" ) ) { - if ( IS_MATCH_EXT( "READ" ) ) + if ( IS_MATCH_EXT( "READ" ) ) { transFlags |= TRA_con; return true; @@ -719,7 +720,7 @@ void IscConnection::parseReservingTable( char *& string, char *& tpbBuffer, shor lockMode = isc_tpb_lock_write; } - else + else IS_MATCH_EXT( "READ" ); if ( countTable ) @@ -836,7 +837,7 @@ int IscConnection::buildParamTransaction( char *& string, char boolDeclare ) transFlags |= TRA_nw; continue; } - + if ( IS_MATCH_EXT( "RECORD_VERSION" ) ) throw SQLEXCEPTION( SYNTAX_ERROR, "NO RECORD_VERSION use only with READ COMMITTED" ); @@ -873,7 +874,7 @@ int IscConnection::buildParamTransaction( char *& string, char boolDeclare ) } continue; } - + if ( IS_MATCH_EXT( "AUTOCOMMIT" ) ) { transFlags |= TRA_autocommit; @@ -927,7 +928,7 @@ int IscConnection::buildParamTransaction( char *& string, char boolDeclare ) transFlags |= TRA_rrl; parseReservingTable( ptOut, text, transFlags ); } - + if ( IS_MATCH_EXT( "USING" ) ) { transFlags |= TRA_inc; @@ -1009,7 +1010,7 @@ class CSchemaIdentifier remove(); } void remove() - { + { stringSql = NULL; deleteNode = false; quotedNode = false; @@ -1017,7 +1018,7 @@ class CSchemaIdentifier lengthNameNode = 0; } CSchemaIdentifier & operator =(const CSchemaIdentifier & src) - { + { stringSql = src.stringSql; deleteNode = src.deleteNode; quotedNode = src.quotedNode; @@ -1235,10 +1236,10 @@ bool IscConnection::removeSchemaFromSQL( char *strSql, int lenSql, char *strSqlO memcpy( &ptOut[offset], &beg[offsetNode], length ); offset += length; offsetNode += length; - + if ( node->deleteNode ) itsDdelete = true; - else + else { int countTbl = countTblNodesShema; @@ -1246,7 +1247,7 @@ bool IscConnection::removeSchemaFromSQL( char *strSql, int lenSql, char *strSqlO while( countTbl-- ) { - if ( node->lengthNameNode == nodeTbl->lengthNameNode + if ( node->lengthNameNode == nodeTbl->lengthNameNode && !strncasecmp( &beg[node->begNameNode], &beg[nodeTbl->begNameNode], node->lengthNameNode ) ) @@ -1337,7 +1338,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, { bool mixed = false; char * pt = ptIn; - + if ( ISUPPER ( *ptIn ) ) { while ( IS_IDENT ( *pt ) ) @@ -1366,7 +1367,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, if ( mixed ) { *ptOut++ = delimiter; - + while ( IS_IDENT ( *ptIn ) ) *ptOut++ = *ptIn++; @@ -1510,7 +1511,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, memcpy(ptOut, nameTinyint, lenNameTinyint); ptOut += lenNameTinyint; } - else + else SKIP_NO_WHITE ( ptOut ); } } @@ -1531,7 +1532,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, // On a note ++ignoreBracket; // ignored { } if ( *ptIn == '?' || IS_MATCH( ptIn, "CALL" ) ) - { + { if ( *ptIn == '?' ) { ptIn++; @@ -1560,7 +1561,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, memmove(ptOut + offset, ptOut, strlen(ptOut) + 1 ); memset(ptOut, ' ', lenSpase); savePtOut = ptOut; - ptIn += offset; + ptIn += offset; ptOut += lenSpase; char procedureName[256]; @@ -1591,7 +1592,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, { if ( quote == *ptIn ) break; - + *end++ = *ptIn++; } else @@ -1634,7 +1635,7 @@ int IscConnection::getNativeSql (const char * inStatementText, int textLength1, *end++ = UPPER(*ptIn), ++ptIn; } while ( repeatWhile ); - + *end = '\0'; int numIn, numOut; @@ -1847,16 +1848,6 @@ int IscConnection::getConnectionCharsetCode() return attachment->charsetCode; } -WCSTOMBS IscConnection::getConnectionWcsToMbs() -{ - return adressWcsToMbs( attachment->charsetCode ); -} - -MBSTOWCS IscConnection::getConnectionMbsToWcs() -{ - return adressMbsToWcs( attachment->charsetCode ); -} - int IscConnection::hasRole(const char * schemaName, const char * roleName) { NOT_YET_IMPLEMENTED; @@ -2007,7 +1998,7 @@ int IscConnection::getInfoItem(char * buffer, int infoItem, int defaultValue) p += length; } - return defaultValue; + return defaultValue; } JString IscConnection::getInfoString(char * buffer, int infoItem, const char * defaultString) @@ -2022,7 +2013,7 @@ JString IscConnection::getInfoString(char * buffer, int infoItem, const char * d p += length; } - return defaultString; + return defaultString; } Properties* IscConnection::allocProperties() diff --git a/IscDbc/IscConnection.h b/IscDbc/IscConnection.h index bd92ed34..428eb00a 100644 --- a/IscDbc/IscConnection.h +++ b/IscDbc/IscConnection.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -42,7 +42,7 @@ class InfoTransaction ~InfoTransaction(); void setParam( const InfoTransaction &src ) - { + { transactionIsolation = src.transactionIsolation; transactionExtInit = src.transactionExtInit; autoCommit = src.autoCommit; @@ -63,7 +63,7 @@ class IscDatabaseMetaData; class Attachment; class IscUserEvents; -class IscConnection : public Connection +class IscConnection : public Connection { public: enum TypeTransaction { TRANSACTION_NONE, TRANSACTION_READ_COMMITTED, TRANSACTION_READ_UNCOMMITTED , @@ -128,8 +128,6 @@ class IscConnection : public Connection virtual void sqlExecuteCreateDatabase(const char * sqlString); virtual void ping(); virtual int getConnectionCharsetCode(); - virtual WCSTOMBS getConnectionWcsToMbs(); - virtual MBSTOWCS getConnectionMbsToWcs(); virtual int hasRole (const char *schemaName, const char *roleName); virtual PropertiesEvents* allocPropertiesEvents(); virtual UserEvents* prepareUserEvents( PropertiesEvents *context, callbackEvent astRoutine, void *userAppData = 0 ); diff --git a/IscDbc/IscDbc.h b/IscDbc/IscDbc.h index f9827d0d..682b23f6 100644 --- a/IscDbc/IscDbc.h +++ b/IscDbc/IscDbc.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -99,7 +99,7 @@ throw SQLEXCEPTION ( connection->GDS->getSqlCode( statusVector ), statusVector [ throw SQLEXCEPTION (CONVERSION_ERROR, "Error conversion") #else #define CONVERSION_CHECK_DEBUG(bool_assign) -#endif +#endif #ifdef _WINDOWS @@ -170,7 +170,7 @@ typedef unsigned __int64 UQUAD; #define MACRO_TO_STR_(s) #s #define MACRO_TO_STR(s) MACRO_TO_STR_(s) -namespace IscDbcLibrary +namespace IscDbcLibrary { int getTypeStatement(IscConnection *connection, Firebird::IStatement* Stmt,const void * buffer, int bufferLength, int *lengthPtr); int getInfoCountRecordsStatement(IscConnection *connection, Firebird::IStatement* Stmt,const void * buffer, int bufferLength, int *lengthPtr); @@ -180,8 +180,6 @@ int getWalDatabase(IscConnection *connection, const void * info_buffer, int buff int strBuildStatInformations(const void * info_buffer, int bufferLength,short *lengthPtr); void getStatInformations(IscConnection *connection, char bVanCall); int getStatInformations(IscConnection *connection, const void * info_buffer, int bufferLength,short *lengthPtr); -int findCharsetsCode( const char *charset ); -int getCharsetSize( int charsetCode ); }; // end namespace IscDbcLibrary #endif diff --git a/IscDbc/IscHeadSqlVar.h b/IscDbc/IscHeadSqlVar.h index 38fb53b8..e137a5a2 100644 --- a/IscDbc/IscHeadSqlVar.h +++ b/IscDbc/IscHeadSqlVar.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -19,13 +19,14 @@ */ // IscHeadSqlVar.h: interface for the IscHeadSqlVar class. -// +// ////////////////////////////////////////////////////////////////////// #if !defined(_ISCHEADSQLVAR_H_) #define _ISCHEADSQLVAR_H_ #include "Sqlda.h" +#include "MultibyteConvert.h" namespace IscDbcLibrary { @@ -63,7 +64,7 @@ class IscHeadSqlVar : public HeadSqlVar } inline void setTypeText() - { + { if (sqlvar->sqltype != SQL_TEXT) { if (sqlvar->sqltype != SQL_VARYING) sqlvar->sqlsubtype = 0; diff --git a/IscDbc/IscStatementMetaData.cpp b/IscDbc/IscStatementMetaData.cpp index 3f31d1fc..45e7e453 100644 --- a/IscDbc/IscStatementMetaData.cpp +++ b/IscDbc/IscStatementMetaData.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -166,7 +166,7 @@ const char* IscStatementMetaData::getSchemaName(int index) const char* IscStatementMetaData::getCatalogName(int index) { - return ""; + return ""; } void IscStatementMetaData::createBlobDataTransfer(int index, Blob *& ptDataBlob) @@ -210,18 +210,6 @@ void IscStatementMetaData::getSqlData(int index, Blob *& ptDataBlob, HeadSqlVar createBlobDataTransfer(index, ptDataBlob); } -WCSTOMBS IscStatementMetaData::getAdressWcsToMbs( int index ) -{ - int charsetCode = isBlobOrArray( index ) ? statement->connection->getConnectionCharsetCode() : sqlda->getSubType( index ) & 0xff; - return adressWcsToMbs( charsetCode ); -} - -MBSTOWCS IscStatementMetaData::getAdressMbsToWcs( int index ) -{ - int charsetCode = isBlobOrArray( index ) ? statement->connection->getConnectionCharsetCode() : sqlda->getSubType( index ) & 0xff; - return adressMbsToWcs( charsetCode ); -} - int IscStatementMetaData::objectVersion() { return STATEMENTMETADATA_VERSION; diff --git a/IscDbc/IscStatementMetaData.h b/IscDbc/IscStatementMetaData.h index fb0dbb4a..40e21b85 100644 --- a/IscDbc/IscStatementMetaData.h +++ b/IscDbc/IscStatementMetaData.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -32,7 +32,7 @@ namespace IscDbcLibrary { class Sqlda; class IscConnection; -class IscStatementMetaData : public StatementMetaData +class IscStatementMetaData : public StatementMetaData { public: virtual int objectVersion(); @@ -62,8 +62,6 @@ class IscStatementMetaData : public StatementMetaData virtual const char* getCatalogName (int index); virtual void getSqlData(int index, Blob *& ptDataBlob, HeadSqlVar *& ptHeadSqlVar); virtual void createBlobDataTransfer(int index, Blob *& ptDataBlob); - virtual WCSTOMBS getAdressWcsToMbs( int index ); - virtual MBSTOWCS getAdressMbsToWcs( int index ); IscStatementMetaData(IscStatement *stmt, Sqlda *ptSqlda); diff --git a/IscDbc/LoadFbClientDll.h b/IscDbc/LoadFbClientDll.h index 2b0f973c..4193c576 100644 --- a/IscDbc/LoadFbClientDll.h +++ b/IscDbc/LoadFbClientDll.h @@ -3,20 +3,20 @@ #ifdef _WINDOWS #include +#include #endif #include -#include #include namespace IscDbcLibrary { -typedef ISC_STATUS ISC_EXPORT create_database (ISC_STATUS ISC_FAR *, - short, - char ISC_FAR *, - isc_db_handle ISC_FAR *, - short, - char ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT create_database (ISC_STATUS ISC_FAR *, + short, + char ISC_FAR *, + isc_db_handle ISC_FAR *, + short, + char ISC_FAR *, short); typedef ISC_STATUS ISC_EXPORT array_gen_sdl(ISC_STATUS ISC_FAR*, @@ -63,46 +63,46 @@ typedef ISC_STATUS ISC_EXPORT array_put_slice(ISC_STATUS ISC_FAR*, void ISC_FAR*, ISC_LONG ISC_FAR*); -typedef ISC_STATUS ISC_EXPORT attach_database (ISC_STATUS ISC_FAR *, - short, - char ISC_FAR *, - isc_db_handle ISC_FAR *, - short, +typedef ISC_STATUS ISC_EXPORT attach_database (ISC_STATUS ISC_FAR *, + short, + char ISC_FAR *, + isc_db_handle ISC_FAR *, + short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT detach_database (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT detach_database (ISC_STATUS ISC_FAR *, isc_db_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT drop_database (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT drop_database (ISC_STATUS ISC_FAR *, isc_db_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT database_info (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, - short, - char ISC_FAR *, - short, +typedef ISC_STATUS ISC_EXPORT database_info (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, + short, + char ISC_FAR *, + short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_execute_immediate (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, - isc_tr_handle ISC_FAR *, - unsigned short, - char ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT dsql_execute_immediate (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, + isc_tr_handle ISC_FAR *, + unsigned short, + char ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT open_blob2 (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT open_blob2 (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, isc_tr_handle ISC_FAR *, - isc_blob_handle ISC_FAR *, - ISC_QUAD ISC_FAR *, - short, + isc_blob_handle ISC_FAR *, + ISC_QUAD ISC_FAR *, + short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT create_blob (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, - isc_tr_handle ISC_FAR *, - isc_blob_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT create_blob (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, + isc_tr_handle ISC_FAR *, + isc_blob_handle ISC_FAR *, ISC_QUAD ISC_FAR *); typedef ISC_STATUS ISC_EXPORT create_blob2(ISC_STATUS ISC_FAR*, @@ -113,31 +113,31 @@ typedef ISC_STATUS ISC_EXPORT create_blob2(ISC_STATUS ISC_FAR*, short, char ISC_FAR*); -typedef ISC_STATUS ISC_EXPORT close_blob (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT close_blob (ISC_STATUS ISC_FAR *, isc_blob_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT cancel_blob (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT cancel_blob (ISC_STATUS ISC_FAR *, isc_blob_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT get_segment (ISC_STATUS ISC_FAR *, - isc_blob_handle ISC_FAR *, - unsigned short ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT get_segment (ISC_STATUS ISC_FAR *, + isc_blob_handle ISC_FAR *, + unsigned short ISC_FAR *, + unsigned short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT put_segment (ISC_STATUS ISC_FAR *, - isc_blob_handle ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT put_segment (ISC_STATUS ISC_FAR *, + isc_blob_handle ISC_FAR *, + unsigned short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT blob_info (ISC_STATUS ISC_FAR *, - isc_blob_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT blob_info (ISC_STATUS ISC_FAR *, + isc_blob_handle ISC_FAR *, + short, + char ISC_FAR *, short, - char ISC_FAR *, - short, char ISC_FAR *); -typedef ISC_LONG ISC_EXPORT vax_integer (char ISC_FAR *, +typedef ISC_LONG ISC_EXPORT vax_integer (char ISC_FAR *, short); typedef ISC_STATUS ISC_EXPORT_VARARG start_transaction(ISC_STATUS ISC_FAR*, @@ -146,23 +146,23 @@ typedef ISC_STATUS ISC_EXPORT_VARARG start_transaction(ISC_STATUS ISC_FAR*, typedef ISC_LONG ISC_EXPORT sqlcode (ISC_STATUS ISC_FAR *); -typedef void ISC_EXPORT sql_interprete (short, - char ISC_FAR *, +typedef void ISC_EXPORT sql_interprete (short, + char ISC_FAR *, short); -typedef ISC_STATUS ISC_EXPORT interprete (char ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT interprete (char ISC_FAR *, ISC_STATUS ISC_FAR * ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT que_events (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, - ISC_LONG ISC_FAR *, - short, - char ISC_FAR *, - isc_callback, +typedef ISC_STATUS ISC_EXPORT que_events (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, + ISC_LONG ISC_FAR *, + short, + char ISC_FAR *, + isc_callback, void ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT cancel_events (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT cancel_events (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, ISC_LONG ISC_FAR *); typedef ISC_STATUS ISC_EXPORT wait_for_event(ISC_STATUS ISC_FAR *, @@ -171,21 +171,21 @@ typedef ISC_STATUS ISC_EXPORT wait_for_event(ISC_STATUS ISC_FAR *, char *, char *); -typedef ISC_STATUS ISC_EXPORT start_multiple (ISC_STATUS ISC_FAR *, - isc_tr_handle ISC_FAR *, - short, +typedef ISC_STATUS ISC_EXPORT start_multiple (ISC_STATUS ISC_FAR *, + isc_tr_handle ISC_FAR *, + short, void ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT commit_transaction (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT commit_transaction (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT commit_retaining (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT commit_retaining (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT rollback_transaction (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT rollback_transaction (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT rollback_retaining (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT rollback_retaining (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *); typedef ISC_STATUS ISC_EXPORT prepare_transaction2 (ISC_STATUS ISC_FAR *, @@ -193,66 +193,66 @@ typedef ISC_STATUS ISC_EXPORT prepare_transaction2 (ISC_STATUS ISC_FAR *, unsigned short, const unsigned char ISC_FAR * ); -typedef ISC_STATUS ISC_EXPORT dsql_allocate_statement (ISC_STATUS ISC_FAR *, - isc_db_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT dsql_allocate_statement (ISC_STATUS ISC_FAR *, + isc_db_handle ISC_FAR *, isc_stmt_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_describe (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT dsql_describe (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_describe_bind (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT dsql_describe_bind (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_execute (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT dsql_execute (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, + isc_stmt_handle ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_execute2 (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT dsql_execute2 (ISC_STATUS ISC_FAR *, isc_tr_handle ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, + isc_stmt_handle ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_fetch (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT dsql_fetch (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_free_statement (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT dsql_free_statement (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, unsigned short); -typedef ISC_STATUS ISC_EXPORT dsql_prepare (ISC_STATUS ISC_FAR *, - isc_tr_handle ISC_FAR *, - isc_stmt_handle ISC_FAR *, - unsigned short, - char ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT dsql_prepare (ISC_STATUS ISC_FAR *, + isc_tr_handle ISC_FAR *, + isc_stmt_handle ISC_FAR *, + unsigned short, + char ISC_FAR *, + unsigned short, XSQLDA ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT dsql_set_cursor_name (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, - char ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT dsql_set_cursor_name (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, + char ISC_FAR *, unsigned short); -typedef ISC_STATUS ISC_EXPORT dsql_sql_info (ISC_STATUS ISC_FAR *, - isc_stmt_handle ISC_FAR *, - short, - char ISC_FAR *, - short, +typedef ISC_STATUS ISC_EXPORT dsql_sql_info (ISC_STATUS ISC_FAR *, + isc_stmt_handle ISC_FAR *, + short, + char ISC_FAR *, + short, char ISC_FAR *); -typedef void ISC_EXPORT decode_date (ISC_QUAD ISC_FAR *, +typedef void ISC_EXPORT decode_date (ISC_QUAD ISC_FAR *, void ISC_FAR *); -typedef void ISC_EXPORT encode_date (void ISC_FAR *, +typedef void ISC_EXPORT encode_date (void ISC_FAR *, ISC_QUAD ISC_FAR *); typedef int ISC_EXPORT add_user (ISC_STATUS ISC_FAR *, USER_SEC_DATA *); @@ -260,24 +260,24 @@ typedef int ISC_EXPORT delete_user (ISC_STATUS ISC_FAR *, USER_SEC_DATA *); typedef int ISC_EXPORT modify_user (ISC_STATUS ISC_FAR *, USER_SEC_DATA *); -typedef ISC_STATUS ISC_EXPORT service_attach (ISC_STATUS ISC_FAR *, - unsigned short, +typedef ISC_STATUS ISC_EXPORT service_attach (ISC_STATUS ISC_FAR *, + unsigned short, char ISC_FAR *, - isc_svc_handle ISC_FAR *, - unsigned short, + isc_svc_handle ISC_FAR *, + unsigned short, char ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT service_detach (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT service_detach (ISC_STATUS ISC_FAR *, isc_svc_handle ISC_FAR *); -typedef ISC_STATUS ISC_EXPORT service_query (ISC_STATUS ISC_FAR *, +typedef ISC_STATUS ISC_EXPORT service_query (ISC_STATUS ISC_FAR *, isc_svc_handle ISC_FAR *, isc_resv_handle ISC_FAR *, - unsigned short, - char ISC_FAR *, - unsigned short, - char ISC_FAR *, - unsigned short, + unsigned short, + char ISC_FAR *, + unsigned short, + char ISC_FAR *, + unsigned short, char ISC_FAR *); typedef ISC_STATUS ISC_EXPORT service_start (ISC_STATUS ISC_FAR *, @@ -286,22 +286,22 @@ typedef ISC_STATUS ISC_EXPORT service_start (ISC_STATUS ISC_FAR *, unsigned short, char ISC_FAR*); -typedef void ISC_EXPORT decode_sql_date (ISC_DATE ISC_FAR *, +typedef void ISC_EXPORT decode_sql_date (ISC_DATE ISC_FAR *, void ISC_FAR *); -typedef void ISC_EXPORT decode_sql_time (ISC_TIME ISC_FAR *, +typedef void ISC_EXPORT decode_sql_time (ISC_TIME ISC_FAR *, void ISC_FAR *); -typedef void ISC_EXPORT decode_timestamp (ISC_TIMESTAMP ISC_FAR *, +typedef void ISC_EXPORT decode_timestamp (ISC_TIMESTAMP ISC_FAR *, void ISC_FAR *); -typedef void ISC_EXPORT encode_sql_date (void ISC_FAR *, +typedef void ISC_EXPORT encode_sql_date (void ISC_FAR *, ISC_DATE ISC_FAR *); -typedef void ISC_EXPORT encode_sql_time (void ISC_FAR *, +typedef void ISC_EXPORT encode_sql_time (void ISC_FAR *, ISC_TIME ISC_FAR *); -typedef void ISC_EXPORT encode_timestamp (void ISC_FAR *, +typedef void ISC_EXPORT encode_timestamp (void ISC_FAR *, ISC_TIMESTAMP ISC_FAR *); typedef void ISC_EXPORT print_blr(char ISC_FAR*, @@ -371,7 +371,7 @@ class CFbDll void *_Handle; #endif - int _CFbDllVersion; + int _CFbDllVersion; // FbClient.Dll Entry Points create_database* _create_database; diff --git a/IscDbc/MultibyteConvert.cpp b/IscDbc/MultibyteConvert.cpp index 992e9a83..4e64df85 100644 --- a/IscDbc/MultibyteConvert.cpp +++ b/IscDbc/MultibyteConvert.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -27,383 +27,343 @@ #else #include #endif +#include #include #include #include "IscDbc.h" #include "Mlist.h" #include "MultibyteConvert.h" -#define CODE_CHARSETS(name,code,size) {#name,sizeof(#name)-1,code,size}, +#ifdef _WINDOWS +#define CODE_CHARSETS(name,code,size,codepage,codeset) {#name,sizeof(#name)-1,code,size,codepage}, +#else +#define CODE_CHARSETS(name,code,size,codepage,codeset) {#name,sizeof(#name)-1,code,size,codeset}, +#endif // _WINDOWS + +namespace +{ -namespace IscDbcLibrary { +#ifdef _WINDOWS +// We cannot left it undefined +#define SQLWCHAR_ENCODING nullptr +#else +#ifndef __BYTE_ORDER__ +#error "Undefined byte order" +#endif +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +const char constexpr *SQLWCHAR_ENCODING = sizeof(SQLWCHAR) == 2 ? "UTF16LE" : "UTF32LE"; +#else +const char constexpr *SQLWCHAR_ENCODING = sizeof(SQLWCHAR) == 2 ? "UTF16BE" : "UTF32BE"; +#endif +#endif struct IntlCharsets { + static constexpr unsigned INVALID_CP = 0xBADC0DE; char *name; short lengthName; short code; short size; - -} const listCharsets[] = { - - CODE_CHARSETS( NONE , 0, 1 ) - CODE_CHARSETS( OCTETS , 1, 1 ) - CODE_CHARSETS( ASCII , 2, 1 ) - CODE_CHARSETS( UNICODE_FSS , 3, 3 ) - CODE_CHARSETS( UTF8 , 4, 4 ) - CODE_CHARSETS( SJIS_0208 , 5, 2 ) - CODE_CHARSETS( EUJC_0208 , 6, 2 ) - CODE_CHARSETS( JIS_0208 , 7, 2 ) - CODE_CHARSETS( UNICODE_UCS2 , 8, 3 ) - CODE_CHARSETS( DOS737 , 9, 1 ) - CODE_CHARSETS( DOS437 , 10, 1 ) - CODE_CHARSETS( DOS850 , 11, 1 ) - CODE_CHARSETS( DOS865 , 12, 1 ) - CODE_CHARSETS( DOS860 , 13, 1 ) - CODE_CHARSETS( DOS863 , 14, 1 ) - CODE_CHARSETS( DOS775 , 15, 1 ) - CODE_CHARSETS( DOS858 , 16, 1 ) - CODE_CHARSETS( DOS862 , 17, 1 ) - CODE_CHARSETS( DOS864 , 18, 1 ) - CODE_CHARSETS( NEXT , 19, 1 ) - CODE_CHARSETS( NEXT , 20, 1 ) - CODE_CHARSETS( ISO8859_1 , 21, 1 ) - CODE_CHARSETS( ISO8859_2 , 22, 1 ) - CODE_CHARSETS( ISO8859_3 , 23, 1 ) - CODE_CHARSETS( NEXT , 24, 1 ) - CODE_CHARSETS( NEXT , 25, 1 ) - CODE_CHARSETS( NEXT , 26, 1 ) - CODE_CHARSETS( NEXT , 27, 1 ) - CODE_CHARSETS( NEXT , 28, 1 ) - CODE_CHARSETS( NEXT , 29, 1 ) - CODE_CHARSETS( NEXT , 30, 1 ) - CODE_CHARSETS( NEXT , 31, 1 ) - CODE_CHARSETS( NEXT , 32, 1 ) - CODE_CHARSETS( NEXT , 33, 1 ) - CODE_CHARSETS( ISO8859_4 , 34, 1 ) - CODE_CHARSETS( ISO8859_5 , 35, 1 ) - CODE_CHARSETS( ISO8859_6 , 36, 1 ) - CODE_CHARSETS( ISO8859_7 , 37, 1 ) - CODE_CHARSETS( ISO8859_8 , 38, 1 ) - CODE_CHARSETS( ISO8859_9 , 39, 1 ) - CODE_CHARSETS( ISO8859_13 , 40, 1 ) - CODE_CHARSETS( NEXT , 41, 1 ) - CODE_CHARSETS( NEXT , 42, 1 ) - CODE_CHARSETS( NEXT , 43, 1 ) - CODE_CHARSETS( KSC_5601 , 44, 2 ) - CODE_CHARSETS( DOS852 , 45, 1 ) - CODE_CHARSETS( DOS857 , 46, 1 ) - CODE_CHARSETS( DOS861 , 47, 1 ) - CODE_CHARSETS( DOS866 , 48, 1 ) - CODE_CHARSETS( DOS869 , 49, 1 ) - CODE_CHARSETS( CYRL , 50, 1 ) - CODE_CHARSETS( WIN1250 , 51, 1 ) - CODE_CHARSETS( WIN1251 , 52, 1 ) - CODE_CHARSETS( WIN1252 , 53, 1 ) - CODE_CHARSETS( WIN1253 , 54, 1 ) - CODE_CHARSETS( WIN1254 , 55, 1 ) - CODE_CHARSETS( BIG_5 , 56, 2 ) - CODE_CHARSETS( GB2312 , 57, 2 ) - CODE_CHARSETS( WIN1255 , 58, 1 ) - CODE_CHARSETS( WIN1256 , 59, 1 ) - CODE_CHARSETS( WIN1257 , 60, 1 ) +#ifdef _WINDOWS + unsigned codePage; +#else + const char* codeset; +#endif // _WINDOWS + +} constexpr listCharsets[] = { + + CODE_CHARSETS( NONE , 0, 1, 0, "" ) + CODE_CHARSETS( OCTETS , 1, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( ASCII , 2, 1, 20127, "ANSI_X3.4-1968" ) + CODE_CHARSETS( UNICODE_FSS , 3, 3, 65001, "UTF-8" ) + CODE_CHARSETS( UTF8 , 4, 4, 65001, "UTF-8" ) + CODE_CHARSETS( SJIS_0208 , 5, 2, 932, "CP932" ) + CODE_CHARSETS( EUJC_0208 , 6, 2, 20932, "EUJP-MS" ) + CODE_CHARSETS( JIS_0208 , 7, 2, 20932, "EUC-JP" ) + CODE_CHARSETS( UNICODE_UCS2 , 8, 3, IntlCharsets::INVALID_CP, "UCS-2" ) + CODE_CHARSETS( DOS737 , 9, 1, 737, "CP737" ) + CODE_CHARSETS( DOS437 , 10, 1, 437, "CP437" ) + CODE_CHARSETS( DOS850 , 11, 1, 850, "CP850" ) + CODE_CHARSETS( DOS865 , 12, 1, 865, "CP865" ) + CODE_CHARSETS( DOS860 , 13, 1, 860, "CP860" ) + CODE_CHARSETS( DOS863 , 14, 1, 863, "CP863" ) + CODE_CHARSETS( DOS775 , 15, 1, 775, "CP775" ) + CODE_CHARSETS( DOS858 , 16, 1, 858, "CP858" ) + CODE_CHARSETS( DOS862 , 17, 1, 862, "CP862" ) + CODE_CHARSETS( DOS864 , 18, 1, 864, "CP864" ) + CODE_CHARSETS( NEXT , 19, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 20, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( ISO8859_1 , 21, 1, 28591, "ISO-8859_1" ) + CODE_CHARSETS( ISO8859_2 , 22, 1, 28592, "ISO-8859_2" ) + CODE_CHARSETS( ISO8859_3 , 23, 1, 28593, "ISO-8859_3" ) + CODE_CHARSETS( UNUSED , 24, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 25, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 26, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 27, 1, IntlCharsets::INVALID_CP, nullptr ) + // Abuse this otherwise unused code for platform-dependent excoding of SQLWCHAR + CODE_CHARSETS( UNUSED , 28, 2, IntlCharsets::INVALID_CP, SQLWCHAR_ENCODING ) + CODE_CHARSETS( UNUSED , 29, 2, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 30, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 31, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 32, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 33, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( ISO8859_4 , 34, 1, 28594, "ISO-8859_4" ) + CODE_CHARSETS( ISO8859_5 , 35, 1, 28595, "ISO-8859_5" ) + CODE_CHARSETS( ISO8859_6 , 36, 1, 28596, "ISO-8859_6" ) + CODE_CHARSETS( ISO8859_7 , 37, 1, 28597, "ISO-8859_7" ) + CODE_CHARSETS( ISO8859_8 , 38, 1, 28598, "ISO-8859_8" ) + CODE_CHARSETS( ISO8859_9 , 39, 1, 28599, "ISO-8859_9" ) + CODE_CHARSETS( ISO8859_13 , 40, 1, 28603, "ISO-8859_13" ) + CODE_CHARSETS( UNUSED , 41, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 42, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 43, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( KSC_5601 , 44, 2, 949, "CP949" ) + CODE_CHARSETS( DOS852 , 45, 1, 852, "CP852" ) + CODE_CHARSETS( DOS857 , 46, 1, 857, "CP857" ) + CODE_CHARSETS( DOS861 , 47, 1, 861, "CP861" ) + CODE_CHARSETS( DOS866 , 48, 1, 866, "CP866" ) + CODE_CHARSETS( DOS869 , 49, 1, 869, "CP869" ) + CODE_CHARSETS( CYRL , 50, 1, 1251, "CP1251" ) + CODE_CHARSETS( WIN1250 , 51, 1, 1250, "CP1250" ) + CODE_CHARSETS( WIN1251 , 52, 1, 1251, "CP1251" ) + CODE_CHARSETS( WIN1252 , 53, 1, 1252, "CP1252" ) + CODE_CHARSETS( WIN1253 , 54, 1, 1253, "CP1253" ) + CODE_CHARSETS( WIN1254 , 55, 1, 1254, "CP1254" ) + CODE_CHARSETS( BIG_5 , 56, 2, 950, "BIG-5" ) + CODE_CHARSETS( GB2312 , 57, 2, 936, "GB2312" ) + CODE_CHARSETS( WIN1255 , 58, 1, 1255, "CP1255" ) + CODE_CHARSETS( WIN1256 , 59, 1, 1256, "CP1256" ) + CODE_CHARSETS( WIN1257 , 60, 1, 1257, "CP1257" ) + CODE_CHARSETS( UNUSED , 61, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( UNUSED , 62, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( KOI8R , 63, 1, 20866, "KOI8R" ) + CODE_CHARSETS( KOI8U , 64, 1, 21866, "KOI8U" ) + CODE_CHARSETS( WIN1258 , 65, 1, 1258, "CP1258" ) + CODE_CHARSETS( TIS620 , 66, 1, 874, "TIS620" ) + CODE_CHARSETS( GBK , 67, 1, IntlCharsets::INVALID_CP, "GBK" ) + CODE_CHARSETS( CP943C , 68, 1, IntlCharsets::INVALID_CP, nullptr ) + CODE_CHARSETS( GB18030 , 69, 1, 54936, "GB18030" ) }; #define SIZE_OF_LISTCHARSETS ( sizeof( listCharsets ) / sizeof( *listCharsets ) ) -int findCharsetsCode( const char *charset ) +static constexpr bool checkTheList() { - const IntlCharsets *p = listCharsets; - const IntlCharsets *end = listCharsets + SIZE_OF_LISTCHARSETS; - - while ( p < end ) + for (int i = 0; i < SIZE_OF_LISTCHARSETS; i++) { - if ( !strncasecmp( charset, p->name, p->lengthName ) ) - { - return p->code; - } - ++p; + if (listCharsets[i].code != i) + return false; } - - return 0; -} - -int getCharsetSize( int charsetCode ) -{ - if ( charsetCode > 0 ) charsetCode &= 0xff; - if ( charsetCode < 0 || charsetCode > SIZE_OF_LISTCHARSETS ) - return 1; - return listCharsets[ charsetCode ].size; + return true; } -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -WCSTOMBS adressWcsToMbs( int charsetCode ) -{ - switch ( charsetCode ) - { - case 3: // UNICODE_FSS - return (WCSTOMBS)fss_wcstombs; - case 4: // UTF8 - return (WCSTOMBS)utf8_wcstombs; - case 0: // NONE - default: - break; - } - -#ifdef _WINDOWS - return _WcsToMbs; -#else - return wcstombs; -#endif -} - -MBSTOWCS adressMbsToWcs( int charsetCode ) -{ - switch ( charsetCode ) - { - case 3: // UNICODE_FSS - return (MBSTOWCS)fss_mbstowcs; - case 4: // UTF8 - return (MBSTOWCS)utf8_mbstowcs; - case 0: // NONE - default: - break; - } -#ifdef _WINDOWS - return _MbsToWcs; -#else - return mbstowcs; -#endif -} +static_assert(checkTheList(), "Some charset missing"); typedef struct -{ - int cmask; - int cval; - int shift; - int lmask; - int lval; +{ + unsigned int cmask; + unsigned int cval; + unsigned int shift; + unsigned int lmask; + unsigned int lval; -} Tab; +} Tab; -static Tab tab[] = +static Tab tab[] = { - 0x80, 0x00, 0*6, 0x7F, 0, // 1 byte sequence - 0xE0, 0xC0, 1*6, 0x7FF, 0x80, // 2 byte sequence - 0xF0, 0xE0, 2*6, 0xFFFF, 0x800, // 3 byte sequence - 0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, // 4 byte sequence - 0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, // 5 byte sequence - 0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, // 6 byte sequence + 0x80, 0x00, 0, 0x7F, 0, // 1 byte sequence + 0xE0, 0xC0, 1, 0x7FF, 0x80, // 2 byte sequence + 0xF0, 0xE0, 2, 0xFFFF, 0x800, // 3 byte sequence + 0xF8, 0xF0, 3, 0x1FFFFF, 0x10000, // 4 byte sequence + 0xFC, 0xF8, 4, 0x3FFFFFF, 0x200000, // 5 byte sequence + 0xFE, 0xFC, 5, 0x7FFFFFFF, 0x4000000, // 6 byte sequence 0, -}; +}; -unsigned int fss_mbstowcs( wchar_t *wcs, const char *mbs, unsigned int lengthForMBS ) +// These functions almost match IConv::convert() specs, except +// wcsLength is in characters, not bytes +static int fss_mbstowcs(const char* &mbs, ssize_t &mbsLength, SQLWCHAR* &wcs, size_t& wcsLength) { - int l, c0, c; - bool bContinue = true; - Tab *t; - unsigned int length = 0; - - if ( !mbs || !*mbs ) - return 0; + size_t length = 0; - const char *mbsEnd = mbs + lengthForMBS; + const char *mbsEnd = mbs + mbsLength; - if ( wcs != NULL ) + if (wcs != nullptr) { - do + while (mbs < mbsEnd && length < wcsLength) { - l = c0 = *mbs & 0xff; + unsigned c0 = static_cast(*mbs); + SQLWCHAR l = c0; - for ( t = tab; t->cmask; t++) - { - ++mbs; - if ( mbs > mbsEnd ) - { - *wcs = L'\0'; - return length; - } + // If we have an incomplete input, mbs must not be advanced. + for (Tab* t = tab; t->cmask; t++) + { if ( ( c0 & t->cmask ) == t->cval ) - { - l &= t->lmask; - - if ( l < t->lval ) + { + if (mbs + t->shift >= mbsEnd) { - bContinue = false; - break; + // Incomplete input sequence + wcsLength = length; + return Convert::Error::CS_INCOMPLETE_INPUT; } - - *wcs++ = (wchar_t)l; - if ( (wchar_t)l == L'\0' ) - return length; + l &= ~t->cmask; - length++; - break; - } + // This routine is supposed to convert data from server and + // the data is already validated so invalid sequence is impossible. + // Omit check for that. - if ( !*mbs ) - { - bContinue = false; - break; - } + switch (t->shift) + { + case 5: + { + l << 6; + l |= *(++mbs) & 0x3f; + [[fallthrough]]; + } + case 4: + { + l << 6; + l |= *(++mbs) & 0x3f; + [[fallthrough]]; + } + case 3: + { + l << 6; + l |= *(++mbs) & 0x3f; + [[fallthrough]]; + } + case 2: + { + l << 6; + l |= *(++mbs) & 0x3f; + [[fallthrough]]; + } + case 1: + { + l << 6; + l |= *(++mbs) & 0x3f; + mbsLength -= t->shift; + break; + } + } - c = ( *mbs ^ 0x80 ) & 0xFF; + // Ignore overlong encoding - if ( c & 0xC0 ) - { + // Get out of inner loop break; } - - l = ( l << 6 ) | c; } + // If this loop ended "naturally", input sequence is invalid. + // Disregard this case and consume one byte in any case. - } while ( bContinue ); + ++mbs; + --mbsLength; + *wcs++ = l; + ++length; + } } else { - do + // Just calculate total length without further checks + while (mbs < mbsEnd) { - l = c0 = *mbs & 0xff; - - for ( t = tab; t->cmask; t++) - { - ++mbs; - if ( mbs > mbsEnd ) - { - return length; - } + unsigned c0 = static_cast(*mbs); + for (Tab* t = tab; t->cmask; t++) + { if ( ( c0 & t->cmask ) == t->cval ) - { - l &= t->lmask; - - if ( l < t->lval ) + { + if (mbs + t->shift >= mbsEnd) { - bContinue = false; - break; + // Incomplete input sequence + wcsLength = length; + return Convert::Error::CS_INCOMPLETE_INPUT; } - - if ( (wchar_t)l == L'\0' ) - return length; - length++; - break; - } + mbs += t->shift; + mbsLength -= t->shift; - if ( !*mbs ) - { - bContinue = false; break; } - - c = ( *mbs ^ 0x80 ) & 0xFF; - - if ( c & 0xC0 ) - { - break; - } - - l = ( l << 6 ) | c; } - - } while ( bContinue ); + ++mbs; + --mbsLength; + ++length; + } } - return length; + wcsLength = length; + + return 0; } -unsigned int fss_wcstombs( char *mbs, const wchar_t *wcs, unsigned int lengthForMBS ) -{ - int l; - int c; - Tab *t; - unsigned int length = 0; +static int fss_wcstombs(const SQLWCHAR* &wcs, ssize_t& wcsLength, char* &mbs, size_t& mbsLength) +{ + size_t length = 0; - if ( !wcs || !*wcs ) - return 0; + // Conditions "wcs == nullptr" and "wcsLength == 0" should be already checked by calling code - if ( mbs != NULL ) + if (mbs != NULL) { do { - l = *wcs; + unsigned l = *wcs; - for ( t = tab; t->cmask; t++ ) - { + for (const Tab* t = tab; t->cmask; t++ ) + { if ( l <= t->lmask ) - { - c = t->shift; - *mbs++ = (char)(t->cval | ( l >> c )); - ++length; - while ( c > 0 ) - { - c -= 6; - *(mbs++) = (char)(0x80 | ( ( l >> c ) & 0x3F )); + { + unsigned c = t->shift; + if (length < mbsLength - c) // "All or nothing" + { + *mbs++ = (char)(t->cval | ( l >> (c * 6) )); ++length; - } + while ( c > 0 ) + { + --c; + *(mbs++) = (char)(0x80 | ( ( l >> (c * 6) ) & 0x3F )); + ++length; + } + ++wcs; + } + else + { + mbsLength = length; + return 0; + } break; - } - } + } + } - } while ( *(++wcs) != L'\0' ); + } while ( --wcsLength > 0 ); } else { do { - l = *wcs; + unsigned l = *wcs++; - for ( t = tab; t->cmask; t++ ) - { + for (const Tab* t = tab; t->cmask; t++ ) + { if ( l <= t->lmask ) - { - c = t->shift; - ++length; - while ( c > 0 ) - { - c -= 6; - ++length; - } + { + // Just count needed bytes + length += t->shift + 1; break; - } - } + } + } - } while ( *(++wcs) != L'\0' ); + } while ( --wcsLength > 0 ); } - return length; + mbsLength = length; + return 0; } - -// Conversion error codes -#define CS_TRUNCATION_ERROR 1 // output buffer too small -#define CS_CONVERT_ERROR 2 // can't remap a character -#define CS_BAD_INPUT 3 // input string detected as bad - #define CS_CANT_MAP 0 // Flag table entries that don't map -#ifndef USHORT -typedef unsigned short USHORT; -#endif -typedef signed int int32_t; -typedef int32_t UChar32; -typedef wchar_t UChar; -typedef signed char int8_t; -typedef int8_t UBool; -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; - -UChar32 utf8_nextCharSafeBody( const uint8_t *s, - int32_t *pi, - int32_t length, - UChar32 c, - UBool strict ); - #define U_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) #define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) @@ -412,8 +372,8 @@ UChar32 utf8_nextCharSafeBody( const uint8_t *s, ((uint32_t)(c)<=0xfdef || ((c)&0xfffe)==0xfffe) && \ (uint32_t)(c)<=0x10ffff) -#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) -#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) +#define U16_LEAD(supplementary) (uint32_t)(((supplementary)>>10)+0xd7c0) +#define U16_TRAIL(supplementary) (uint32_t)(((supplementary)&0x3ff)|0xdc00) #define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) #define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) #define U16_GET_SUPPLEMENTARY(lead, trail) \ @@ -478,277 +438,569 @@ const uint8_t utf8_countTrailBytes[256] = 3, 3, 3, // illegal in Unicode 4, 4, 4, 4, // illegal in Unicode 5, 5, // illegal in Unicode - 0, 0 // illegal bytes 0xfe and 0xff + 5, 5 // illegal bytes 0xfe and 0xff }; -static const UChar32 -utf8_minLegal[4]={ 0, 0x80, 0x800, 0x10000 }; +//static const UChar32 +//utf8_minLegal[4]={ 0, 0x80, 0x800, 0x10000 }; #define UTF8_COUNT_TRAIL_BYTES(leadByte) (utf8_countTrailBytes[(uint8_t)leadByte]) -#define UTF8_MASK_LEAD_BYTE(leadByte, countTrailBytes) ((leadByte)&=(1<<(6-(countTrailBytes)))-1) +#define UTF8_MASK_LEAD_BYTE(leadByte, countTrailBytes) ((leadByte)&=(1<<(7-(countTrailBytes)))-1) #define UTF8_ERROR_VALUE_1 0x15 #define UTF8_ERROR_VALUE_2 0x9f #define UTF_ERROR_VALUE 0xffff #define U_SENTINEL (-1) -static const UChar32 utf8_errorValue[6] = -{ - UTF8_ERROR_VALUE_1, - UTF8_ERROR_VALUE_2, - UTF_ERROR_VALUE, - 0x10ffff, - 0x3ffffff, - 0x7fffffff -}; - -unsigned int utf8_mbstowcs( wchar_t *wcs, const char *mbs, unsigned int lengthForMBS ) +//static const UChar32 utf8_errorValue[6] = +//{ +// UTF8_ERROR_VALUE_1, +// UTF8_ERROR_VALUE_2, +// UTF_ERROR_VALUE, +// 0x10ffff, +// 0x3ffffff, +// 0x7fffffff +//}; + +static int utf8_mbstowcs(const char* &mbs, ssize_t& mbsLength, SQLWCHAR* &wcs, size_t& wcsLength) { - USHORT err_code = 0; - ULONG err_position = 0; - - if ( !wcs ) - return lengthForMBS * sizeof( *wcs ); + int err_code = 0; - const UCHAR* mbsOrg = (const UCHAR*)mbs; - const UCHAR* const mbsEnd = mbsOrg + lengthForMBS; - const USHORT* const wcsStart = (const USHORT*)wcs; + const char* const mbsEnd = mbs + mbsLength; + const SQLWCHAR* const wcsEnd = wcs + wcsLength; + size_t length = 0; - for ( ULONG i = 0; i < lengthForMBS; ) + while (mbs < mbsEnd) { - UChar32 c = mbsOrg[i++]; + uint32_t c = static_cast(*mbs); + uint8_t count = UTF8_COUNT_TRAIL_BYTES( c ); - if ( c <= 0x7F ) + if (mbs + count < mbsEnd) { - if ( !c ) + uint8_t trail = 0, illegal = 0; + size_t i = 0; + + UTF8_MASK_LEAD_BYTE( c, count ); + + switch ( count ) + { + // each branch falls through to the next one + case 5: + case 4: + // count>=4 is always illegal: no more than 3 trail bytes in Unicode's UTF-8 + illegal = 1; break; - *wcs++ = c; - } - else - { - err_position = i - 1; - c = utf8_nextCharSafeBody( mbsOrg, - reinterpret_cast(&i), - lengthForMBS, - c, - -1 ); + case 3: + trail = mbs[++i]; + c = ( c << 6) | ( trail & 0x3f ); + illegal |= ( trail & 0xc0 ) ^ 0x80; + [[fallthrough]]; + case 2: + trail = mbs[++i]; + c = ( c << 6) | ( trail & 0x3f ); + illegal |= ( trail & 0xc0 ) ^ 0x80; + [[fallthrough]]; + case 1: + trail = mbs[++i]; + c = ( c << 6) | ( trail & 0x3f ); + illegal |= ( trail & 0xc0 ) ^ 0x80; + break; - if ( c < 0 ) + case 0: + break; + } + +/* Firebird is a trusted source, skip validation + // All the error handling should return a value + // that needs count bytes so that UTF8_GET_CHAR_SAFE() works right. + // + // Starting with Unicode 3.0.1, non-shortest forms are illegal. + // Starting with Unicode 3.2, surrogate code points must not be + // encoded in UTF-8, and there are no irregular sequences any more. + // + // U8_ macros (new in ICU 2.4) return negative values for error conditions. + + // correct sequence - all trail bytes have (b7..b6)==(10)? + // illegal is also set if count>=4 + // + if ( illegal || c < utf8_minLegal[count] || U_IS_SURROGATE( c ) ) { - err_code = CS_BAD_INPUT; + // error handling + uint8_t errorCount = count; + // don't go beyond this sequence + i = *pi; + + while ( count > 0 && U8_IS_TRAIL( s[i] ) ) + { + ++i; + --count; + } + + if ( strict >= 0 ) + c = utf8_errorValue[ errorCount - count ]; + else + c = U_SENTINEL; + } + else if ( c > 0x10ffff ) // code point>0x10ffff, outside Unicode + { + error_code = Convert::Error::CS_BAD_INPUT; break; } - else if ( c <= 0xFFFF ) + else if ( strict > 0 && U_IS_UNICODE_NONCHAR( c ) ) + { + // strict: forbid non-characters like U+fffe + c = utf8_errorValue[ count ]; + } +*/ + } + else // too few bytes left + { + err_code = Convert::Error::CS_INCOMPLETE_INPUT; + break; + } + + // Atomic flush character if fits + if constexpr (sizeof(SQLWCHAR) == 4) // iODBC + { + if (wcs != nullptr) + { + if (wcs >= wcsEnd) + { + break; + } *wcs++ = c; - else + } + ++length; + } + else if ( c <= 0xFFFF ) + { + if (wcs != nullptr) { + if (wcs >= wcsEnd) + { + break; + } + *wcs++ = c; + } + ++length; + } + else + { + if (wcs != nullptr) + { + if (wcs + 1 >= wcsEnd) + { + break; + } *wcs++ = U16_LEAD( c ); *wcs++ = U16_TRAIL( c ); } + length += 2; } + ++count; // Include leading byte + mbs += count; + mbsLength -= count; } - *wcs = L'\0'; - return (const USHORT*)wcs - wcsStart; + wcsLength = length; + + return err_code; } -unsigned int utf8_wcstombs( char *mbs, const wchar_t *wcs, unsigned int lengthForMBS ) +static int utf8_wcstombs(const SQLWCHAR* &wcs, ssize_t& wcsLength, char* &mbs, size_t& mbsLength) { - USHORT err_code = 0; - ULONG err_position = 0; - ULONG wcsLen = (ULONG)wcslen( wcs ); - - if ( !wcs || !*wcs ) - return 0; + int err_code = 0; - if ( !mbs ) - return wcsLen * 4; + // if ( !wcs || !*wcs ) already checked in the calling code - const USHORT* wcsOrg = (const USHORT*)wcs; - const USHORT* const wcsEnd = wcsOrg + wcsLen; - UCHAR* mbsOrg = (UCHAR*)mbs; - const UCHAR* const mbsStart = (const UCHAR*)mbsOrg; - const UCHAR* const mbsEnd = (const UCHAR*)mbsOrg + lengthForMBS; + const SQLWCHAR* wcsOrg = wcs; + const SQLWCHAR* wcsEnd = wcs + wcsLength; + const char* const mbsEnd = mbs + mbsLength; + size_t length = 0; - for ( ULONG i = 0; i < wcsLen; ) + while (wcsLength > 0) { - if ( !(mbsEnd - mbsOrg) ) - { - err_code = CS_TRUNCATION_ERROR; - err_position = i * sizeof( *wcsOrg ); - break; - } - - UChar32 c = wcsOrg[i++]; + uint32_t c = *wcs; + size_t wcsLen = 1; - if ( c <= 0x7F ) + if constexpr (sizeof(SQLWCHAR) == 2) // UTF-16 { - if ( !c ) - break; - *mbsOrg++ = c; - } - else - { - err_position = (i - 1) * sizeof( *wcsOrg ); - if ( U_IS_SURROGATE( c ) ) { - UChar32 c2; + uint32_t c2; - if ( U_IS_SURROGATE_LEAD( c ) - && wcsOrg + i < wcsEnd - && U16_IS_TRAIL( c2 = wcsOrg[i] ) ) + if ( U_IS_SURROGATE_LEAD( c ) ) { - ++i; - c = U16_GET_SUPPLEMENTARY( c, c2 ); - } - else - { - err_code = CS_BAD_INPUT; - break; + if (wcs + 1 >= wcsEnd) + { + err_code = Convert::Error::CS_INCOMPLETE_INPUT; + break; + } + if (U16_IS_TRAIL( c2 = wcs[1] ) ) + { + c = U16_GET_SUPPLEMENTARY( c, c2 ); + wcsLen = 2; + } + else + { + err_code = Convert::Error::CS_BAD_INPUT; + break; + } } } - if ( U8_LENGTH( c ) <= mbsEnd - mbsOrg ) + } + else // UTF-32 + { + // Actually nothing to do here, no surrogates in UTF-32 + } + + size_t mbsLen = U8_LENGTH( c ); + if (mbs != nullptr) + { + if (mbsLen <= mbsEnd - mbs) { - if ( (uint32_t)c <= 0x7f ) - *mbsOrg++ = (uint8_t)c; - else + switch (mbsLen) { - if ( (uint32_t)c <= 0x7ff ) - *mbsOrg++ = (uint8_t)( (c >> 6) | 0xc0 ); - else + case 1: { - if ( (uint32_t)c <= 0xffff ) - *mbsOrg++ = (uint8_t)( ( c >> 12 ) | 0xe0 ); - else - { - *mbsOrg++ = (uint8_t)( ( c >> 18 ) | 0xf0 ); - *mbsOrg++ = (uint8_t)(( ( c >> 12 ) & 0x3f ) | 0x80 ); - } - *mbsOrg++ = (uint8_t)(( ( c >> 6 ) & 0x3f ) | 0x80 ); + *mbs++ = (uint8_t)c; + break; } - *mbsOrg++ = (uint8_t) ( ( c & 0x3f ) | 0x80 ); + case 2: + { + *mbs++ = (uint8_t)( (c >> 6) | 0xc0 ); + *mbs++ = (uint8_t)( ( c & 0x3f ) | 0x80 ); + break; + } + case 3: + { + *mbs++ = (uint8_t)( ( c >> 12 ) | 0xe0 ); + *mbs++ = (uint8_t)((( c >> 6 ) & 0x3f ) | 0x80 ); + *mbs++ = (uint8_t)( ( c & 0x3f ) | 0x80 ); + break; + } + case 4: + { + *mbs++ = (uint8_t)( ( c >> 18 ) | 0xf0 ); + *mbs++ = (uint8_t)((( c >> 12 ) & 0x3f ) | 0x80 ); + *mbs++ = (uint8_t)((( c >> 6 ) & 0x3f ) | 0x80 ); + *mbs++ = (uint8_t)( ( c & 0x3f ) | 0x80 ); + } + default: // WTH to do with length 0??? + break; } + } else { - err_code = CS_TRUNCATION_ERROR; + // Truncated output is not an error break; } } + + length += mbsLen; + wcsLength -= wcsLen; + wcs += wcsLen; + } + + mbsLength = length; + return err_code; +} + +} // end namespace + +int findCharsetsCode( const char *charset ) +{ + const IntlCharsets *p = listCharsets; + const IntlCharsets *end = listCharsets + SIZE_OF_LISTCHARSETS; + + while ( p < end ) + { + if ( !strncasecmp( charset, p->name, p->lengthName ) ) + { + return p->code; + } + ++p; } - *mbsOrg = '\0'; - return (unsigned int)( ( mbsOrg - mbsStart ) * sizeof( *mbs ) ); + return 0; +} + +int getCharsetSize( int charsetCode ) +{ + if ( charsetCode > 0 ) charsetCode &= 0xff; + if ( charsetCode < 0 || charsetCode > SIZE_OF_LISTCHARSETS ) + return 1; + return listCharsets[ charsetCode ].size; } -UChar32 utf8_nextCharSafeBody( const uint8_t *s, - int32_t *pi, - int32_t length, - UChar32 c, - UBool strict ) +int Convert::fromWcs(const SQLWCHAR* wcs, ssize_t wcsLength, char* mbs, size_t& mbsLength) { - int32_t i = *pi; - uint8_t count = UTF8_COUNT_TRAIL_BYTES( c ); + if (wcs == nullptr) + { + mbsLength = 0; + return 0; + } + + if (wcsLength == SQL_NTS) + { + wcsLength = SQLWCHAR_len(wcs); + } + + if (wcsLength == 0) + { + mbsLength = 0; + return 0; + } - if ( i + count <= length ) + if (mbs == nullptr) { - uint8_t trail, illegal = 0; + // Ignore garbage + mbsLength = 0; + return 0; + } - UTF8_MASK_LEAD_BYTE( c, count ); + int ret = 0; // ? - // count==0 for illegally leading trail bytes and the illegal bytes 0xfe and 0xff - switch ( count ) + switch (charsetCode) + { + case Charset::Code::Fss: { - // each branch falls through to the next one - case 5: - case 4: - // count>=4 is always illegal: no more than 3 trail bytes in Unicode's UTF-8 - illegal = 1; - break; - - case 3: - trail = s[i++]; - c = ( c << 6) | ( trail & 0x3f ); - if ( c < 0x110 ) - illegal |= ( trail & 0xc0 ) ^ 0x80; - else + ret = fss_wcstombs(wcs, wcsLength, mbs, mbsLength); + break; + } + case Charset::Code::Utf8: + { + ret = utf8_wcstombs(wcs, wcsLength, mbs, mbsLength); + break; + } + default: + { + int ret = iMbs.init(Charset::Code::SqlWchar, charsetCode); + if (ret != 0) { - // code point>0x10ffff, outside Unicode - illegal = 1; - break; - } - case 2: - trail = s[i++]; - c = ( c << 6) | ( trail & 0x3f ); - illegal |= ( trail & 0xc0 ) ^ 0x80; - case 1: - trail = s[i++]; - c = ( c << 6) | ( trail & 0x3f ); - illegal |= ( trail & 0xc0 ) ^ 0x80; - break; - - case 0: - if( strict >= 0 ) - return UTF8_ERROR_VALUE_1; - else - return U_SENTINEL; - // no default branch to optimize switch() - all values are covered - } - - // All the error handling should return a value - // that needs count bytes so that UTF8_GET_CHAR_SAFE() works right. - // - // Starting with Unicode 3.0.1, non-shortest forms are illegal. - // Starting with Unicode 3.2, surrogate code points must not be - // encoded in UTF-8, and there are no irregular sequences any more. - // - // U8_ macros (new in ICU 2.4) return negative values for error conditions. - - // correct sequence - all trail bytes have (b7..b6)==(10)? - // illegal is also set if count>=4 - // - if ( illegal || c < utf8_minLegal[count] || U_IS_SURROGATE( c ) ) + return ret; + } + const char* inBuf = reinterpret_cast(wcs); + ssize_t inLen = wcsLength * sizeof(SQLWCHAR); + + ret = iMbs.convert(inBuf, inLen, mbs, mbsLength); + if (inLen != 0) + { + // Some bytes left unconverted but they will get no second chance. + // Reset possible non-clear state. + iMbs.reset(); + } + + wcsLength = inLen / sizeof(SQLWCHAR); + break; + } + } + + if (ret != 0) + { + return ret; + } + + if (wcsLength != 0) + { + // Some data left unconverted. + ret = Convert::Error::CS_TRUNCATION_ERROR; + } + return ret; +} + +int Convert::toWcs(const char* mbs, ssize_t mbsLength, SQLWCHAR* wcs, size_t& wcsLength) +{ + if (mbs == nullptr) + { + if (wcs != nullptr) + { + *wcs = '\0'; + } + wcsLength = 0; + return 0; + } + + if (mbsLength == SQL_NTS) + { + mbsLength = strlen(mbs); + } + + if (mbsLength == 0) + { + if (wcs != nullptr) { - // error handling - uint8_t errorCount = count; - // don't go beyond this sequence - i = *pi; + *wcs = '\0'; + } + wcsLength = 0; + return 0; + } + + int ret = 0; + size_t length = 0; - while ( count > 0 && U8_IS_TRAIL( s[i] ) ) + if (wcs == nullptr) + { + wcsLength = 0; + } + else + { + length = wcsLength - 1; // Rezerve one codepoint to + switch (charsetCode) + { + case Charset::Code::Fss: + { + ret = fss_mbstowcs(mbs, mbsLength, wcs, length); + break; + } + case Charset::Code::Utf8: { - ++i; - --count; - } - - if ( strict >= 0 ) - c = utf8_errorValue[ errorCount - count ]; - else - c = U_SENTINEL; - } - else if ( strict > 0 && U_IS_UNICODE_NONCHAR( c ) ) + ret = utf8_mbstowcs(mbs, mbsLength, wcs, length); + break; + } + default: + { + int ret = iWcs.init(charsetCode, Charset::Code::SqlWchar); + if (ret != 0) + { + return ret; + } + char* outBuf = reinterpret_cast(wcs); + size_t outLen = length * sizeof(SQLWCHAR); + + ret = iWcs.convert(mbs, mbsLength, outBuf, outLen); + + wcs = reinterpret_cast(outBuf); + length = outLen / sizeof(SQLWCHAR); + break; + } + } + // Force null-termination per ODBC specs + *wcs = '\0'; + } + + if (ret != 0 && ret != Convert::Error::CS_TRUNCATION_ERROR) + { + return ret; + } + + if (mbsLength != 0) + { + // Some data left unconverted, calculate total length. + size_t extraLength = 0; + switch (charsetCode) { - // strict: forbid non-characters like U+fffe - c = utf8_errorValue[ count ]; - } - } - else // too few bytes left + case Charset::Code::Fss: + { + SQLWCHAR* outBuf = nullptr; + ret = fss_mbstowcs(mbs, mbsLength, outBuf, extraLength); + break; + } + case Charset::Code::Utf8: + { + SQLWCHAR* outBuf = nullptr; + ret = utf8_mbstowcs(mbs, mbsLength, outBuf, extraLength); + break; + } + default: + { + // Previous block can be skipped so this initialization is not redunant + int ret = iWcs.init(charsetCode, Charset::Code::SqlWchar); + if (ret != 0) + { + return ret; + } + + char* outBuf = nullptr; + size_t outLen = 0; + + ret = iWcs.convert(mbs, mbsLength, outBuf, outLen); + + extraLength = outLen / sizeof(SQLWCHAR); + break; + } + } + length += extraLength; + } + wcsLength = length; + + return ret; +} + +void Convert::setCharsetCode(short code) +{ + if (code >= 0 && code < SIZE_OF_LISTCHARSETS) { - // error handling - int32_t i0 = i; - // don't just set (i)=(length) in case there is an illegal sequence + charsetCode = code; + } + // else just ignore it because here is no way to report any error. +} - while( i < length && U8_IS_TRAIL( s[i] ) ) - ++i; - if ( strict >= 0 ) - c = utf8_errorValue[ i - i0 ]; - else - c = U_SENTINEL; - } +#ifndef _WINDOWS +int Convert::IConv::init(short fromCharsetCode, short toCharsetCode) +{ + if (cd == (iconv_t)-1) + { + cd = iconv_open(listCharsets[toCharsetCode].codeset, listCharsets[fromCharsetCode].codeset); + if (cd == (iconv_t)-1) + { + return errno; + } + } + return 0; +} + +int Convert::IConv::convert(const char* &inBuf, ssize_t& inBytesLeft, char* &outBuf, size_t& outBytes) +{ + if (outBuf == nullptr) + { + // Just calculate number of needed bytes. + // It is pity that iconv cannot operate without output buffer. + char buf[1024]; + outBytes = 0; - *pi = i; - return c; + while (inBytesLeft > 0) + { + char* p = buf; + size_t l = sizeof(buf); + int res = iconv(cd, const_cast(&inBuf), reinterpret_cast(&inBytesLeft), &p, &l); + if (res == (size_t)-1) + { + if (errno != E2BIG) + { + // Reset conversion state to prevent dirty output on the next call + iconv(cd, nullptr, nullptr, nullptr, nullptr); + return errno; + } + } + outBytes += p - buf; + } + } + else + { + char* begin = outBuf; + int res = iconv(cd, const_cast(&inBuf), reinterpret_cast(&inBytesLeft), &outBuf, &outBytes); + if (res == (size_t)-1) + { + if (errno != E2BIG) + { + // Reset conversion state to prevent dirty output on the next call + iconv(cd, nullptr, nullptr, nullptr, nullptr); + return errno; + } + } + outBytes = outBuf - begin; + } + + return 0; } -}; // end namespace IscDbcLibrary +void Convert::IConv::reset() +{ + iconv(cd, nullptr, nullptr, nullptr, nullptr); +} +#else + +#endif diff --git a/IscDbc/MultibyteConvert.h b/IscDbc/MultibyteConvert.h index d90d77e9..dcce0319 100644 --- a/IscDbc/MultibyteConvert.h +++ b/IscDbc/MultibyteConvert.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -21,31 +21,140 @@ // MultibyteConvert.h // ////////////////////////////////////////////////////////////////////// +// +// Firebird API uses data in a connection charset (mostly) +// ODBC API uses data either in ANSI or in Unicode +// thus we have two conversion vectors: ANSI <-> CS and WIDE <-> CS. +// +// ODBC specs require strings returned from driver to be null-terminated +// while Firebird API has separate length variable(s) +// thus conversions WIDE -> CS and ANSI -> CS don't need to terminate the result +// (or rather must not because there is no room in Firebird message buffer for that) +// while conversions CS -> WIDE and CS -> ANSI must do it. +// +// ODBC has conception of piecewise data transfer and generally ODBC strings +// can be much longer that Firebird so conversions to/from CLOB must be piecewise +// with special care about blob segments border cut multibyte sequence in half. +// +// Fortunately, conversions ANSI <-> WIDE are not needed (?) +// +// A side note: what must not be overseen is error messages. They can contain +// object names and data, and are converted into connection charset. With connection +// charset NONE a message about UC violation can become quite messy with constraint +// and field names in UTF-8 but data in field's charset (WIN1252 for example). +// Because of this it is better to enforce usage of a connection charset defaulting +// it to UTF-8 + +#pragma once -#if !defined(_MultibyteConvert_H_) -#define _MultibyteConvert_H_ +#ifndef _WINDOWS +#include +#else +#include +#endif +#include -namespace IscDbcLibrary { +#include -class MultibyteConvert; +namespace Charset +{ + enum Code : short // To avoid magic numbers in code. Must correspond to IntlCharsets.code + { + None = 0, + Fss = 3, + Utf8 = 4, + SqlWchar = 28 // Either UTF-16 or UTF-32 depending on size of SQLWCHAR + }; +} + +// May be not optimal but it solves the problematic case sizeof(SQLWCHAR) != sizeof(wchar_t) +// which prevent standard functions from been used. +inline size_t SQLWCHAR_len(const SQLWCHAR* wcs) +{ + for (size_t result = 0; ; ++result) + { + if (*wcs++ == 0) + { + return result; + } + } +} -class CMultibyteConvert +class Convert { + struct IConv + { + #ifndef _WINDOWS + iconv_t cd = (iconv_t)-1; + + ~IConv() + { + if (cd != (iconv_t)-1) + { + iconv_close(cd); + } + } + #else + UINT srcCodepage; + UINT tgtCodepage; + #endif + + int init(short fromCharsetCode, short toCharsetCode); + // On input outBytes is size of outBuf, on return outBytes is number of used bytes. + // If outBuf is nullptr, input value of outBytes is ignored. + // On return inBuf is advanced and inBytesLeft is number of bytes left unconverted. + int convert(const char* &inBuf, ssize_t& inBytesLeft, char* &outBuf, size_t& outBytes); + // Force reset conversion state. + void reset(); + }; + + IConv iMbs, iWcs; + short charsetCode = Charset::Code::None; + public: + static constexpr unsigned maxUtfBytes = 4; + + // Conversion error codes + enum Error + { +#ifdef _WINDOWS + CS_TRUNCATION_ERROR = ERROR_BUFFER_TOO_SMALL, + CS_BAD_INPUT = ERROR_NO_UNICODE_TRANSLATION, + CS_INCOMPLETE_INPUT = EINVAL // Not the best choice but MultiByteToWideChar() doesn't treat incomplete sequence separately from invalid sequence anyway +#else + CS_TRUNCATION_ERROR = E2BIG, + CS_BAD_INPUT = EILSEQ, // input string detected as bad + CS_INCOMPLETE_INPUT = EINVAL +#endif + }; - CMultibyteConvert() + Convert() = default; + Convert(short charset) { + setCharsetCode(charset); } -}; -MBSTOWCS adressMbsToWcs( int charsetCode ); -WCSTOMBS adressWcsToMbs( int charsetCode ); + // Has no effect after any conversion has been done. + void setCharsetCode(short code); + + // wcsLength is length of wcs in characters (SQL_NTS is ok). + // mbsLength on input is size of buffer in bytes, on output used number of bytes. + // Return value is 0 on success, an error code otherwise. + int fromWcs(const SQLWCHAR* wcs, ssize_t wcsLength, char* mbs, size_t& mbsLength); -unsigned int fss_mbstowcs( wchar_t *wcs, const char *mbs, unsigned int length ); -unsigned int fss_wcstombs( char *mbs, const wchar_t *wcs, unsigned int length ); -unsigned int utf8_mbstowcs( wchar_t *wcs, const char *mbs, unsigned int lengthForMBS ); -unsigned int utf8_wcstombs( char *mbs, const wchar_t *wcs, unsigned int lengthForMBS ); + // These functions always convert as much as possible and always terminate output string with . + // Still they return full length of output as per ODBC specs. + // Insufficient buffer is not considered an error and should be detected by returned xxxLength. -}; // end namespace IscDbcLibrary + // wcsLength is in characters, the rest is as above. + int toWcs(const char* mbs, ssize_t mbsLength, SQLWCHAR* wcs, size_t& wcsLength); + + // In contrast to function above stops as soon as output buffer is full. + + // mbsLength on return is the number of consumed bytes. It should make calling code + // simpler in the case if input is a stream, not just a big buffer. + int toWcsPiecewise(const char* mbs, ssize_t& mbsLength, SQLWCHAR* wcs, size_t& wcsLength); +}; -#endif // !defined(_MultibyteConvert_H_) +int findCharsetsCode(const char* charset); +int getCharsetSize(int charsetCode); diff --git a/IscDbc/Sqlda.cpp b/IscDbc/Sqlda.cpp index 4754c833..c51dbb26 100644 --- a/IscDbc/Sqlda.cpp +++ b/IscDbc/Sqlda.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -19,7 +19,7 @@ * * 2002-11-25 Sqlda.cpp * Contributed by C. G. Alvarez - * Changes to support better handling of + * Changes to support better handling of * NUMERIC and DECIMAL * * 2002-10-11 Sqlda.cpp @@ -34,9 +34,9 @@ * * 2002-08-02 Sqlda.cpp * Contributed by C. G. Alvarez - * Change getColumnType to pass var->sqlscale to getSQLType. - * Change getSQLTypeName to keep in sync with this. - * The purpose is to allow return of DECIMAL as JDBC_DECIMAL + * Change getColumnType to pass var->sqlscale to getSQLType. + * Change getSQLTypeName to keep in sync with this. + * The purpose is to allow return of DECIMAL as JDBC_DECIMAL * instead of JDBC_BIGINT. * * 2002-06-04 Sqlda.cpp @@ -61,6 +61,7 @@ #include "IscConnection.h" #include "IscStatement.h" #include "IscBlob.h" +#include "MultibyteConvert.h" using namespace Firebird; @@ -269,7 +270,7 @@ class CDataStaticCursor countBlocks += 10; listBlocks.resize( countBlocks ); } - + if ( listBlocks.at(curBlock).rows.size() == 0 ) { listBlocks.at(curBlock) = { nMAXROWBLOCK, lenRow }; @@ -524,7 +525,7 @@ void Sqlda::mapSqlAttributes( IscStatement *stmt ) //arrays if( stmt && var->sqltype == SQL_ARRAY ) { var->array = new CAttrArray; - /* + /* * loadAttributes() raises an SQLError exc on empty relname / sqlname * Empty names are common case for input parameters. * But it seems to me, we have no need for var->array attributes for inputs. @@ -676,7 +677,7 @@ void Sqlda::print() // Warning! // It's hack, for exclude system filed description -// Return SQLDA for all system field has 31 length +// Return SQLDA for all system field has 31 length // and charsetId 3 (UNICODE_FSS) it's error! // // if ( !(var->sqllen % getCharsetSize( var->sqlsubtype )) ) @@ -702,14 +703,14 @@ int Sqlda::getColumnDisplaySize(int index) return SET_INFO_FROM_SUBTYPE( MAX_NUMERIC_SHORT_LENGTH + 2, MAX_DECIMAL_SHORT_LENGTH + 2, MAX_SMALLINT_LENGTH + 1); - + case SQL_LONG: return SET_INFO_FROM_SUBTYPE( MAX_NUMERIC_LONG_LENGTH + 2, MAX_DECIMAL_LONG_LENGTH + 2, MAX_INT_LENGTH + 1); case SQL_FLOAT: - return MAX_FLOAT_LENGTH + 4; + return MAX_FLOAT_LENGTH + 4; case SQL_D_FLOAT: case SQL_DOUBLE: @@ -722,7 +723,7 @@ int Sqlda::getColumnDisplaySize(int index) return SET_INFO_FROM_SUBTYPE( MAX_NUMERIC_LENGTH + 2, MAX_DECIMAL_LENGTH + 2, MAX_QUAD_LENGTH + 1); - + case SQL_ARRAY: return Var(index)->array->arrOctetLength; // return MAX_ARRAY_LENGTH; @@ -798,11 +799,11 @@ int Sqlda::getPrecision(int index) MAX_DECIMAL_LENGTH, MAX_QUAD_LENGTH); - case SQL_ARRAY: + case SQL_ARRAY: return var->array->arrOctetLength; // return MAX_ARRAY_LENGTH; - - case SQL_BLOB: + + case SQL_BLOB: return MAX_BLOB_LENGTH; case SQL_TYPE_TIME: @@ -1017,16 +1018,16 @@ void Sqlda::setValue(int slot, Value * value, IscStatement *stmt) switch (var->sqltype) { - case SQL_BLOB: + case SQL_BLOB: setBlob (var, value, stmt); return; - case SQL_ARRAY: + case SQL_ARRAY: setArray (var, value, stmt); return; } var->sqlscale = 0; - + if( value->type == Null ) { setNull( index ); return; @@ -1043,7 +1044,7 @@ void Sqlda::setValue(int slot, Value * value, IscStatement *stmt) { /* case Null: - + var->sqltype |= 1; *var->sqlind = sqlNull; break; @@ -1095,22 +1096,22 @@ void Sqlda::setValue(int slot, Value * value, IscStatement *stmt) var->sqllen = sizeof (ISC_DATE); *(ISC_DATE*)dst_buf = IscStatement::getIscDate (value->data.date); break; - + case TimeType: var->sqltype = SQL_TYPE_TIME; var->sqllen = sizeof (ISC_TIME); *(ISC_TIME*)dst_buf = IscStatement::getIscTime (value->data.time); break; - + case Timestamp: var->sqltype = SQL_TIMESTAMP; var->sqllen = sizeof (ISC_TIMESTAMP); *(ISC_TIMESTAMP*)dst_buf = IscStatement::getIscTimeStamp (value->data.timestamp); break; - + default: NOT_YET_IMPLEMENTED; - } + } } @@ -1186,10 +1187,10 @@ void Sqlda::setBlob(CAttrSqlVar* var, Value * value, IscStatement *stmt) break; case Date: - + default: NOT_YET_IMPLEMENTED; - } + } if ( length ) { diff --git a/Main.cpp b/Main.cpp index 58e51a1a..5dfd184b 100644 --- a/Main.cpp +++ b/Main.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -22,9 +22,9 @@ * 2003-03-24 main.cpp * Contributed by Roger Gammans * Fix SQLError prototype to match the prototype - * in the sql.h header file. This stops g++ - * generating SQLError as a C++ name-mangled - * entry point. A C function entry is used + * in the sql.h header file. This stops g++ + * generating SQLError as a C++ name-mangled + * entry point. A C function entry is used * allowing correct binding to the driver manager. * * 2002-10-11 main.cpp @@ -56,10 +56,10 @@ * * 2002-04-30 main.cpp - * Added suggestions by Carlos G Alvarez + * Added suggestions by Carlos G Alvarez * o Test for logfile before trying to close it. * o Changed parameter types for SQLSetConnectOption - * + * */ #ifdef _WINDOWS @@ -89,7 +89,7 @@ void logMsg (const char *msg) } } #endif - + void notYetImplemented (const char *msg) { LOG_MSG (msg); @@ -139,7 +139,7 @@ BOOL APIENTRY DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved } #endif -static SQLRETURN __SQLAllocHandle( SQLSMALLINT handleType, SQLHANDLE inputHandle, +static SQLRETURN __SQLAllocHandle( SQLSMALLINT handleType, SQLHANDLE inputHandle, SQLHANDLE *outputHandle ) { TRACE ("__SQLAllocHandle"); @@ -194,14 +194,14 @@ SQLRETURN SQL_API SQLAllocStmt( SQLHDBC hDbc, SQLHSTMT *hStmt ) ///// SQLBindCol ///// ODBC 1.0 ///// ISO 92 -SQLRETURN SQL_API SQLBindCol( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, - SQLSMALLINT targetType, SQLPOINTER targetValue, +SQLRETURN SQL_API SQLBindCol( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, + SQLSMALLINT targetType, SQLPOINTER targetValue, SQLLEN bufferLength, SQLLEN *strLen_or_Ind ) { TRACE ("SQLBindCol"); GUARD_HSTMT( hStmt ); - return ((OdbcStatement*) hStmt)->sqlBindCol( columnNumber, targetType, targetValue, + return ((OdbcStatement*) hStmt)->sqlBindCol( columnNumber, targetType, targetValue, bufferLength, strLen_or_Ind ); } @@ -241,7 +241,7 @@ SQLRETURN SQL_API SQLConnect( SQLHDBC hDbc, SQLRETURN ret = ((OdbcConnection*) hDbc)->sqlConnect( serverName, nameLength1, userName, nameLength2, authentication, nameLength3 ); - LOG_PRINT(( logFile, + LOG_PRINT(( logFile, "SQLConnect : Line %d\n" " +status : %d\n" " +hDbc : %p\n" @@ -260,15 +260,15 @@ SQLRETURN SQL_API SQLConnect( SQLHDBC hDbc, ///// SQLDescribeCol ///// ODBC 1.0 ///// ISO 92 SQLRETURN SQL_API SQLDescribeCol( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, - SQLCHAR *columnName, SQLSMALLINT bufferLength, - SQLSMALLINT *nameLength, SQLSMALLINT *dataType, + SQLCHAR *columnName, SQLSMALLINT bufferLength, + SQLSMALLINT *nameLength, SQLSMALLINT *dataType, SQLULEN *columnSize, SQLSMALLINT *decimalDigits, SQLSMALLINT *nullable ) { TRACE ("SQLDescribeCol"); GUARD_HSTMT( hStmt ); - return ((OdbcStatement*) hStmt)->sqlDescribeCol( columnNumber, columnName, bufferLength, + return ((OdbcStatement*) hStmt)->sqlDescribeCol( columnNumber, columnName, bufferLength, nameLength, dataType, columnSize, decimalDigits, nullable ); } @@ -306,7 +306,7 @@ SQLRETURN SQL_API SQLError( SQLHENV hEnv, msgBufferLength, msgLength ); } if ( hEnv ) - return ((OdbcEnv*)hEnv)->sqlError( sqlState, nativeErrorCode, msgBuffer, + return ((OdbcEnv*)hEnv)->sqlError( sqlState, nativeErrorCode, msgBuffer, msgBufferLength, msgLength ); return SQL_ERROR; @@ -338,7 +338,7 @@ SQLRETURN SQL_API SQLFetch( SQLHSTMT hStmt ) { TRACE ("SQLFetch"); GUARD_HSTMT( hStmt ); - + return ((OdbcStatement*) hStmt)->sqlFetch(); } @@ -407,7 +407,7 @@ SQLRETURN SQL_API SQLPrepare( SQLHSTMT hStmt, { TRACE ("SQLPrepare"); GUARD_HSTMT( hStmt ); - + return ((OdbcStatement*) hStmt)->sqlPrepare( statementText, textLength ); } @@ -496,7 +496,7 @@ SQLRETURN SQL_API SQLDriverConnect( SQLHDBC hDbc, SQLHWND hWnd, SQLCHAR *szConnS SQLRETURN ret = ((OdbcConnection*) hDbc)->sqlDriverConnect( hWnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion ); - LOG_PRINT(( logFile, + LOG_PRINT(( logFile, "SQLDriverConnect : Line %d\n" " +status : %d\n" " +hDbc : %p\n" @@ -540,7 +540,14 @@ SQLRETURN SQL_API SQLGetData( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLLEN bufferLength, SQLLEN *strLen_or_Ind ) { - TRACE ("SQLGetData"); + LOG_PRINT((logFile, "SQLGetData:\n" + " +hStmt : %p\n" + " +columnNumber : %u\n" + " +targetType : %d\n" + " +bufferLength : %lu\n" + " +lenOrInd : %p\n\n" + , hStmt, columnNumber, targetType, bufferLength, strLen_or_Ind)); + GUARD_HSTMT( hStmt ); return ((OdbcStatement*) hStmt)->sqlGetData( columnNumber, targetType, targetValue, @@ -552,7 +559,12 @@ SQLRETURN SQL_API SQLGetData( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, SQLRETURN SQL_API SQLGetFunctions( SQLHDBC hDbc, SQLUSMALLINT functionId, SQLUSMALLINT *supported ) { - TRACE ("SQLGetFunctions"); + LOG_PRINT((logFile, "SQLGetFunctions:\n" + " +hDbc : %p\n" + " +functionId : %u\n" + " +supported ptr : %p\n\n" + , hDbc, functionId, supported)); + GUARD_HDBC( hDbc ); return ((OdbcConnection*) hDbc)->sqlGetFunctions( functionId, supported ); @@ -602,7 +614,7 @@ SQLRETURN SQL_API SQLParamData( SQLHSTMT hStmt, SQLPOINTER *value ) ///// SQLPutData ///// -SQLRETURN SQL_API SQLPutData( SQLHSTMT hStmt, SQLPOINTER data, SQLLEN strLen_or_Ind ) +SQLRETURN SQL_API SQLPutData( SQLHSTMT hStmt, SQLPOINTER data, SQLLEN strLen_or_Ind ) { TRACE ("SQLPutData"); GUARD_HSTMT( hStmt ); @@ -810,7 +822,7 @@ SQLRETURN SQL_API SQLParamOptions( SQLHSTMT hStmt, SQLULEN cRow, SQLULEN *piRow ///// SQLPrimaryKeys ///// -SQLRETURN SQL_API SQLPrimaryKeys( SQLHSTMT hStmt, +SQLRETURN SQL_API SQLPrimaryKeys( SQLHSTMT hStmt, SQLCHAR *szCatalogName, SQLSMALLINT cbCatalogName, SQLCHAR *szSchemaName, SQLSMALLINT cbSchemaName, SQLCHAR *szTableName, SQLSMALLINT cbTableName ) @@ -1149,15 +1161,15 @@ SQLRETURN SQL_API SQLGetDescField( SQLHDESC hDesc, SQLRETURN SQL_API SQLGetDescRec( SQLHDESC hDesc, SQLSMALLINT recNumber, SQLCHAR *name, SQLSMALLINT bufferLength, SQLSMALLINT *stringLength, - SQLSMALLINT *type, SQLSMALLINT *subType, - SQLLEN *length, SQLSMALLINT *precision, + SQLSMALLINT *type, SQLSMALLINT *subType, + SQLLEN *length, SQLSMALLINT *precision, SQLSMALLINT *scale, SQLSMALLINT *nullable ) { TRACE ("SQLGetDescRec"); GUARD_HDESC( hDesc ); return ((OdbcDesc*) hDesc)->sqlGetDescRec( recNumber, name, - bufferLength, stringLength, type, subType, + bufferLength, stringLength, type, subType, length, precision, scale, nullable ); } @@ -1198,6 +1210,13 @@ SQLRETURN SQL_API SQLGetEnvAttr( SQLHENV hEnv, { TRACE ("SQLGetEnvAttr"); + LOG_PRINT((logFile, "SQLGetEnvAttr:\n" + " +hEnv : %p\n" + " +attribute : %d\n" + " +value : %p\n" + " bufferLength : %d\n\n" + , hEnv, attribute, value, bufferLength)); + return ((OdbcEnv*) hEnv)->sqlGetEnvAttr( attribute, value, bufferLength, stringLength ); } @@ -1270,6 +1289,13 @@ SQLRETURN SQL_API SQLSetEnvAttr( SQLHENV hEnv, { TRACE ("SQLSetEnvAttr"); + LOG_PRINT((logFile, "SQLSetEnvAttr:\n" + " +hEnv : %p\n" + " +attribute : %d\n" + " +value : %p\n" + " stringLength : %d\n\n" + , hEnv, attribute, value, stringLength)); + return ((OdbcEnv*) hEnv)->sqlSetEnvAttr( attribute, value, stringLength ); } diff --git a/MainUnicode.cpp b/MainUnicode.cpp index 1d3c8486..861a5eb5 100644 --- a/MainUnicode.cpp +++ b/MainUnicode.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -27,6 +27,7 @@ #include "OdbcJdbc.h" #include "OdbcEnv.h" #include "OdbcConnection.h" +#include "OdbcConvert.h" #include "OdbcStatement.h" #include "SafeEnvThread.h" #include "Main.h" @@ -45,23 +46,22 @@ extern UINT codePage; // from Main.cpp template class ConvertingString { - enum typestring { NONE, WIDECHARS, BYTESCHARS }; - - SQLCHAR *byteString; - SQLWCHAR *unicodeString; - TypeRealLen *realLength; - int lengthString; - typestring isWhy; - bool returnCountOfBytes; - OdbcConnection *connection; - + char *byteString = nullptr; // Internal buffer in connection charset used for interaction with Firebird API + size_t byteLength = 0; // Length of byteString not including terminating null + SQLWCHAR *unicodeString = nullptr; // User-defined buffer of wide characters + size_t unicodeLength = 0; // Length of unicodeString buffer in characters + TypeRealLen *realLength = nullptr; // Pointer to a variable accepting output data size + bool returnCountOfBytes = false; // if *realLength expect size in bytes (i.e. unicodeString was actually SQLPOINTER in caller code) + OdbcConnection *connection = nullptr; + public: void setConnection( OdbcConnection *connect ) { connection = connect; } - ConvertingString() + ConvertingString() = delete; +/* { isWhy = NONE; returnCountOfBytes = true; @@ -71,167 +71,128 @@ class ConvertingString lengthString = 0; connection = NULL; } +*/ + // Binding of output string ConvertingString( int length, SQLWCHAR *wcString, TypeRealLen *pLength = NULL, bool retCountOfBytes = true ) { - connection = NULL; realLength = pLength; returnCountOfBytes = retCountOfBytes; if ( wcString ) { - isWhy = BYTESCHARS; unicodeString = wcString; - if ( length == SQL_NTS ) - lengthString = 0; + // A strange case but still valid according to ODBC specs: + // BufferLength + // If DiagIdentifier is a driver-defined field, the application indicates the nature of the field + // to the Driver Manager by setting the BufferLength argumant. BufferLength can have the + // following values: + // - If DiagInfoPtr is a pointer to a character string, BufferLength is the length of the + // string or SQL_NTS. + // + // IMHO, it is a bug in specs but unixODBC and iODBC passes the value as is so let's try + // to do something smart. + if (length == SQL_NTS) + unicodeLength = SQLWCHAR_len(wcString) + 1; + + // If DiagInfoPtr is a pointer to a binary string, the application places the result of the + // SQL_LEN_BINARY_ATTR(length) macro in BufferLength. This places a negative value + // in BufferLength + // + // Hardly applicable, but still + if (length < SQL_LEN_BINARY_ATTR_OFFSET) + { + unicodeLength = (SQL_LEN_BINARY_ATTR_OFFSET - length) / sizeof(SQLWCHAR); + } else if ( retCountOfBytes ) - lengthString = length / sizeof(wchar_t); - else - lengthString = length; + { + // In this case length is in bytes, + unicodeLength = length / sizeof(SQLWCHAR); + } + else // Length is in wide characters + { + unicodeLength = length; + } } - else - isWhy = NONE; - Alloc(); + if (unicodeLength) + { + byteLength = unicodeLength * Convert::maxUtfBytes + 1; + // Connection charset is fixed to UTF-8 so every character can take up to 4 bytes + byteString = new char[byteLength]{}; // Null terminator as well + } } + // Binding of input string + // Length is in characters. ConvertingString( OdbcConnection *connect, SQLWCHAR *wcString, int length ) { connection = connect; - realLength = NULL; - unicodeString = NULL; - returnCountOfBytes = true; - isWhy = BYTESCHARS; if ( wcString ) - convUnicodeToString( wcString, length ); - else - { - byteString = NULL; - lengthString = 0; - } - } - - operator SQLCHAR*() { return byteString; } - int getLength() { return lengthString; } - - ~ConvertingString() - { - switch ( isWhy ) { - case BYTESCHARS: - - if ( unicodeString ) + if (length = SQL_NTS) + { + length = SQLWCHAR_len(wcString); + } + if (length > 0) { - size_t len; + byteLength = length * Convert::maxUtfBytes + 1; + byteString = new char[byteLength]; - if ( connection ) - len = connection->MbsToWcs( (wchar_t*)unicodeString, (const char*)byteString, lengthString ); - else + if (connect) { -#ifdef _WINDOWS - len = MultiByteToWideChar( codePage, 0, (const char*)byteString, -1, - unicodeString, lengthString ); - if ( len > 0 ) - len--; -#else - len = mbstowcs( (wchar_t*)unicodeString, (const char*)byteString, lengthString ); -#endif + connect->fromWcs(wcString, length, byteString, byteLength); + // Here error status is lost. That's not good. } - - if ( len > 0 ) + else { - *(LPWSTR)(unicodeString + len) = L'\0'; - - if ( realLength ) - { - if ( returnCountOfBytes ) - *realLength = (TypeRealLen)( len * 2 ); - else - *realLength = (TypeRealLen)len; - } + Convert conv(Charset::Code::Utf8); + conv.fromWcs(wcString, length, byteString, byteLength); } } - - delete[] byteString; - break; - - case NONE: - if ( realLength && returnCountOfBytes ) - *realLength *= 2; - break; } } - SQLCHAR * convUnicodeToString( SQLWCHAR *wcString, int length ) - { - size_t bytesNeeded; - wchar_t *ptEndWC = NULL; - wchar_t saveWC; - - if ( length == SQL_NTS ) - length = (int)wcslen( (const wchar_t*)wcString ); - else if ( wcString[length] != L'\0' ) - { - ptEndWC = (wchar_t*)&wcString[length]; - saveWC = *ptEndWC; - *ptEndWC = L'\0'; - } - - if ( connection ) - bytesNeeded = connection->WcsToMbs( NULL, (const wchar_t*)wcString, length ); - else - { -#ifdef _WINDOWS - bytesNeeded = WideCharToMultiByte( codePage, (DWORD)0, wcString, length, NULL, (int)0, NULL, NULL ); -#else - bytesNeeded = wcstombs( NULL, (const wchar_t*)wcString, length ); -#endif - } - - byteString = new SQLCHAR[ bytesNeeded + 2 ]; + char* data() { return byteString; } + [[depreceted("byteString has connection charset which may be different from ANSI")]] + operator SQLCHAR*() { return reinterpret_cast(byteString); } + int getLength() { return byteLength; } - if ( connection ) - bytesNeeded = connection->WcsToMbs( (char *)byteString, (const wchar_t*)wcString, bytesNeeded ); - else - { -#ifdef _WINDOWS - bytesNeeded = WideCharToMultiByte( codePage, 0, wcString, length, (LPSTR)byteString, (int)bytesNeeded, NULL, NULL ); -#else - bytesNeeded = wcstombs( (char *)byteString, (const wchar_t*)wcString, bytesNeeded ); -#endif - } - - byteString[ bytesNeeded ] = '\0'; - lengthString = (int)bytesNeeded; - - if ( ptEndWC ) - *ptEndWC = saveWC; - - return byteString; - } - -protected: - void Alloc() + // Though this is elegant from code POV, converting in destructor has one problem: + // There is no way to report conversion errors including string right truncation. + // TODO: Rework every instantiation to use explicit conversion with appropriate error handling. + ~ConvertingString() { - switch ( isWhy ) + if ( unicodeString ) { - case BYTESCHARS: - if ( lengthString ) + size_t len = unicodeLength; + ssize_t stringLength = SQL_NTS; + if (realLength) { - byteString = new SQLCHAR[ lengthString + 2 ]; - memset(byteString, 0, lengthString + 2); + stringLength = *realLength; + } + + if ( connection ) + { + connection->toWcs(byteString, stringLength, unicodeString, len); } else - byteString = NULL; - break; - - case NONE: - unicodeString = NULL; - byteString = NULL; - lengthString = 0; - break; + { + Convert conv(Charset::Code::Utf8); + conv.toWcs(byteString, stringLength, unicodeString, len); + } + + if ( realLength ) + { + if ( returnCountOfBytes ) + *realLength = (TypeRealLen)(len * sizeof(SQLWCHAR)); + else + *realLength = (TypeRealLen)len; + } } + + delete[] byteString; } }; @@ -242,7 +203,20 @@ SQLRETURN SQL_API SQLColAttributesW( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, SQLSMALLINT bufferLength, SQLSMALLINT *stringLength, SQLLEN *numericAttribute ) { - TRACE("SQLColAttributesW"); + LOG_PRINT((logFile, + "SQLColAttributesW:\n" + " +hStmt : %p\n" + " +columnNumber : %u\n" + " +fieldIdentifier : %u\n" + " +characterAttribute : %p\n" + " +bufferLength : %u\n" + " +stringLength : %p\n" + " +numericAttribute : %p\n\n" + , hStmt, columnNumber, fieldIdentifier + , characterAttribute, bufferLength, stringLength + , numericAttribute + )); + GUARD_HSTMT( hStmt ); switch ( fieldIdentifier ) @@ -263,15 +237,30 @@ SQLRETURN SQL_API SQLColAttributesW( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, (SQLWCHAR *)characterAttribute, stringLength ); CharacterAttribute.setConnection( GETCONNECT_STMT( hStmt ) ); - return ((OdbcStatement*) hStmt)->sqlColAttribute( columnNumber, fieldIdentifier, - (SQLPOINTER)(SQLCHAR*)CharacterAttribute, CharacterAttribute.getLength(), + SQLRETURN res = ((OdbcStatement*) hStmt)->sqlColAttribute( columnNumber, fieldIdentifier, + (SQLPOINTER)CharacterAttribute.data(), CharacterAttribute.getLength(), stringLength, numericAttribute ); + + LOG_PRINT((logFile, + "SQLColAttributesW return string:\n" + " +characterAttribute : %s\n" + " +stringLength : %d\n\n" + , CharacterAttribute.data(), stringLength == nullptr ? 0 : *stringLength + )); + return res; } } - return ((OdbcStatement*) hStmt)->sqlColAttribute( columnNumber, fieldIdentifier, + SQLRETURN res = ((OdbcStatement*) hStmt)->sqlColAttribute( columnNumber, fieldIdentifier, characterAttribute, bufferLength, stringLength, numericAttribute ); + LOG_PRINT((logFile, + "SQLColAttributesW return number:\n" + " +numericAttribute : %ld\n\n" + , *numericAttribute + )); + + return res; } ///// SQLConnectW ///// ODBC 1.0 ///// ISO 92 @@ -281,28 +270,35 @@ SQLRETURN SQL_API SQLConnectW( SQLHDBC hDbc, SQLWCHAR *userName, SQLSMALLINT nameLength2, SQLWCHAR *authentication, SQLSMALLINT nameLength3 ) { - TRACE ("SQLConnectW"); GUARD_HDBC( hDbc ); - ConvertingString<> ServerName( (OdbcConnection*)hDbc, serverName, nameLength1 ); - ConvertingString<> UserName( (OdbcConnection*)hDbc, userName, nameLength2 ); - ConvertingString<> Authentication( (OdbcConnection*)hDbc, authentication, nameLength3 ); + OdbcConnection* conn = (OdbcConnection*)hDbc; + + // Force UTF-8 connection charset and DPB processing + conn->charsetCode = Charset::Code::Utf8; + conn->charset = "UTF8"; + conn->convert.setCharsetCode(Charset::Code::Utf8); - SQLRETURN ret = ((OdbcConnection*) hDbc)->sqlConnect( ServerName, ServerName.getLength(), UserName, - UserName.getLength(), Authentication, Authentication.getLength() ); - LOG_PRINT(( logFile, + ConvertingString<> ServerName( conn, serverName, nameLength1 ); + ConvertingString<> UserName( conn, userName, nameLength2 ); + ConvertingString<> Authentication( conn, authentication, nameLength3 ); + + SQLRETURN ret = conn->sqlConnect( ServerName, SQL_NTS, + UserName, SQL_NTS, + Authentication, SQL_NTS ); + LOG_PRINT(( logFile, "SQLConnectW : Line %d\n" " +status : %d\n" " +hDbc : %p\n" - " +serverName : %S\n" - " +userName : %S\n" - " +authentication : %S\n\n", + " +serverName : %s\n" + " +userName : %s\n" + " +authentication : %s\n\n", __LINE__, ret, hDbc, - serverName ? serverName : (SQLWCHAR*)"", - userName ? userName : (SQLWCHAR*)"", - authentication ? authentication : (SQLWCHAR*)"" )); + serverName ? ServerName.data() : "", + userName ? UserName.data() : "", + authentication ? Authentication.data() : "" )); return ret; } @@ -311,7 +307,7 @@ SQLRETURN SQL_API SQLConnectW( SQLHDBC hDbc, SQLRETURN SQL_API SQLDescribeColW( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, SQLWCHAR *columnName, SQLSMALLINT bufferLength, - SQLSMALLINT *nameLength, SQLSMALLINT *dataType, + SQLSMALLINT *nameLength, SQLSMALLINT *dataType, SQLULEN *columnSize, SQLSMALLINT *decimalDigits, SQLSMALLINT *nullable ) { @@ -397,7 +393,7 @@ SQLRETURN SQL_API SQLPrepareW( SQLHSTMT hStmt, GUARD_HSTMT( hStmt ); ConvertingString<> StatementText( GETCONNECT_STMT( hStmt ), statementText, textLength ); - + return ((OdbcStatement*) hStmt)->sqlPrepare( StatementText, StatementText.getLength() ); } @@ -443,27 +439,41 @@ SQLRETURN SQL_API SQLDriverConnectW( SQLHDBC hDbc, SQLHWND hWnd, SQLWCHAR *szCon SQLSMALLINT cbConnStrOutMax, SQLSMALLINT *pcbConnStrOut, SQLUSMALLINT fDriverCompletion ) { - TRACE ("SQLDriverConnectW"); GUARD_HDBC( hDbc ); - ConvertingString<> ConnStrIn( (OdbcConnection*)hDbc, szConnStrIn, cbConnStrIn ); + OdbcConnection* conn = (OdbcConnection*)hDbc; + + // Force UTF-8 connection charset and DPB processing + conn->charsetCode = Charset::Code::Utf8; + conn->charset = "UTF8"; + conn->convert.setCharsetCode(Charset::Code::Utf8); + + ConvertingString<> ConnStrIn(conn, szConnStrIn, cbConnStrIn ); ConvertingString<> ConnStrOut( cbConnStrOutMax, szConnStrOut, pcbConnStrOut, false ); - ConnStrOut.setConnection( (OdbcConnection*)hDbc ); + ConnStrOut.setConnection(conn); - SQLRETURN ret = ((OdbcConnection*) hDbc)->sqlDriverConnect( hWnd, ConnStrIn, ConnStrIn.getLength(), - ConnStrOut, ConnStrOut.getLength(), pcbConnStrOut, - fDriverCompletion ); - LOG_PRINT(( logFile, - "SQLDriverConnectW : Line %d\n" - " +status : %d\n" - " +hDbc : %p\n" - " +szConnStrIn : %S\n" - " +szConnStrOut : %S\n\n", - __LINE__, + LOG_PRINT(( logFile, + "SQLDriverConnectW:\n" + " +hDbc : %p\n" + " +szConnStrIn : %s (%d)\n" + " +szConnStrOut : %p (%d)\n\n", + hDbc, + szConnStrIn ? ConnStrIn.data() : "", cbConnStrIn, + szConnStrOut, cbConnStrOutMax )); + + SQLRETURN ret = conn->sqlDriverConnect( hWnd, ConnStrIn, ConnStrIn.getLength(), + ConnStrOut, ConnStrOut.getLength(), pcbConnStrOut, + fDriverCompletion ); + LOG_PRINT(( logFile, + "SQLDriverConnectW return:\n" + " +status : %d\n" + " +hDbc : %p\n" + " +szConnStrIn : %s\n" + " +szConnStrOut : %s\n\n", ret, hDbc, - szConnStrIn ? szConnStrIn : (SQLWCHAR*)"", - szConnStrOut ? szConnStrOut : (SQLWCHAR*)"" )); + szConnStrIn ? ConnStrIn.data() : "", + szConnStrOut ? ConnStrOut.data() : "" )); return ret; } @@ -596,7 +606,7 @@ SQLRETURN SQL_API SQLSetConnectOptionW( SQLHDBC hDbc, SQLUSMALLINT option, SQLUL ConvertingString<> Value( (OdbcConnection*)hDbc, (SQLWCHAR *)value, bufferLength ); - return ((OdbcConnection*) hDbc)->sqlSetConnectAttr( option, + return ((OdbcConnection*) hDbc)->sqlSetConnectAttr( option, (SQLPOINTER)(SQLCHAR*)Value, Value.getLength() ); } } @@ -750,7 +760,7 @@ SQLRETURN SQL_API SQLNativeSqlW( SQLHDBC hDbc, if ( cbSqlStrIn == SQL_NTS ) cbSqlStrIn = (SQLINTEGER)wcslen( (const wchar_t*)szSqlStrIn ); - + bool isByte = !( cbSqlStrIn % 2 ); ConvertingString<> SqlStrIn( (OdbcConnection*)hDbc, szSqlStrIn, cbSqlStrIn ); @@ -764,7 +774,7 @@ SQLRETURN SQL_API SQLNativeSqlW( SQLHDBC hDbc, ///// SQLPrimaryKeysW ///// -SQLRETURN SQL_API SQLPrimaryKeysW( SQLHSTMT hStmt, +SQLRETURN SQL_API SQLPrimaryKeysW( SQLHSTMT hStmt, SQLWCHAR *szCatalogName, SQLSMALLINT cbCatalogName, SQLWCHAR *szSchemaName, SQLSMALLINT cbSchemaName, SQLWCHAR *szTableName, SQLSMALLINT cbTableName ) @@ -910,7 +920,7 @@ SQLRETURN SQL_API SQLColAttributeW( SQLHSTMT hStmt, SQLUSMALLINT columnNumber, if ( bufferLength > 0 ) { - ConvertingString<> CharacterAttribute( bufferLength, + ConvertingString<> CharacterAttribute( bufferLength, (SQLWCHAR *)characterAttribute, stringLength ); CharacterAttribute.setConnection( GETCONNECT_STMT( hStmt ) ); @@ -944,7 +954,7 @@ SQLRETURN SQL_API SQLGetConnectAttrW( SQLHDBC hDbc, ConvertingString Value( bufferLength, (SQLWCHAR *)value, stringLength ); Value.setConnection( (OdbcConnection*)hDbc ); - return ((OdbcConnection*) hDbc)->sqlGetConnectAttr( attribute, + return ((OdbcConnection*) hDbc)->sqlGetConnectAttr( attribute, (SQLPOINTER)(SQLCHAR*)Value, Value.getLength(), stringLength ); } } @@ -956,7 +966,7 @@ SQLRETURN SQL_API SQLGetConnectAttrW( SQLHDBC hDbc, ///// SQLGetDescFieldW ///// SQLRETURN SQL_API SQLGetDescFieldW( SQLHDESC hDesc, SQLSMALLINT recNumber, - SQLSMALLINT fieldIdentifier, SQLPOINTER value, + SQLSMALLINT fieldIdentifier, SQLPOINTER value, SQLINTEGER bufferLength, SQLINTEGER *stringLength ) { TRACE ("SQLGetDescFieldW"); @@ -997,8 +1007,8 @@ SQLRETURN SQL_API SQLGetDescFieldW( SQLHDESC hDesc, SQLSMALLINT recNumber, SQLRETURN SQL_API SQLGetDescRecW( SQLHDESC hDesc, SQLSMALLINT recNumber, SQLWCHAR *name, SQLSMALLINT bufferLength, SQLSMALLINT *stringLength, - SQLSMALLINT *type, SQLSMALLINT *subType, - SQLLEN *length, SQLSMALLINT *precision, + SQLSMALLINT *type, SQLSMALLINT *subType, + SQLLEN *length, SQLSMALLINT *precision, SQLSMALLINT *scale, SQLSMALLINT *nullable ) { TRACE ("SQLGetDescRecW"); @@ -1008,7 +1018,7 @@ SQLRETURN SQL_API SQLGetDescRecW( SQLHDESC hDesc, Name.setConnection( GETCONNECT_DESC( hDesc ) ); return ((OdbcDesc*) hDesc)->sqlGetDescRec( recNumber, Name, Name.getLength(), - stringLength, type, subType, + stringLength, type, subType, length, precision, scale, nullable ); } @@ -1159,7 +1169,7 @@ SQLRETURN SQL_API SQLSetDescFieldW( SQLHDESC hDesc, if ( bufferLength > 0 || bufferLength == SQL_NTS ) { int len; - + if ( bufferLength == SQL_NTS ) len = (int)wcslen( (const wchar_t*)value ); else diff --git a/MbsAndWcs.cpp b/MbsAndWcs.cpp index 40a22638..bbc0ec4a 100644 --- a/MbsAndWcs.cpp +++ b/MbsAndWcs.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * diff --git a/OdbcConnection.cpp b/OdbcConnection.cpp index e079d25e..d80554d8 100644 --- a/OdbcConnection.cpp +++ b/OdbcConnection.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -19,45 +19,45 @@ * * 2003-03-24 OdbcConnection.cpp * Contributed by Norbert Meyer - * delete Statements before close connection - * (statement-destructor needs connection-pointer - * for call connection->deleteStatement. - * If connection->deleteStatement not called, - * you get an AV if you use Statements and call - * SQLDisconnect(...); + * delete Statements before close connection + * (statement-destructor needs connection-pointer + * for call connection->deleteStatement. + * If connection->deleteStatement not called, + * you get an AV if you use Statements and call + * SQLDisconnect(...); * SQLFreeHandle(..., connection); * - * 2002-12-05 OdbcConnection.cpp + * 2002-12-05 OdbcConnection.cpp * Contributed by C. Guzman Alvarez * SQLGetInfo returns more info. * Solve error in SQL_ORDER_BY_COLUMNS_IN_SELECT. * - * 2002-08-12 OdbcConnection.cpp + * 2002-08-12 OdbcConnection.cpp * Contributed by C. G. Alvarez - * Added SQL_API_SQLGETCONNECTOPTION to list of + * Added SQL_API_SQLGETCONNECTOPTION to list of * supported functions * * Added more items to sqlGetInfo() * - * 2002-07-02 OdbcConnection.cpp + * 2002-07-02 OdbcConnection.cpp * Added better management of txn isolation * Added fix to enable setting the asyncEnable property * contributed by C. G. Alvarez * - * 2002-07-01 OdbcConnection.cpp - * Added SQL_API_SQLSETCONNECTOPTION to + * 2002-07-01 OdbcConnection.cpp + * Added SQL_API_SQLSETCONNECTOPTION to * supportedFunctions C. G. Alvarez * * 2002-06-26 OdbcConnection::sqlGetInfo - * Added call to clearErrors() at start of + * Added call to clearErrors() at start of * the method(Roger Gammans). * - * 2002-06-25 OdbcConnection.cpp + * 2002-06-25 OdbcConnection.cpp * Contributed by C. G. Alvarez * Return Database Server Name from sqlGetInfo * * - * 2002-06-08 OdbcConnection.cpp + * 2002-06-08 OdbcConnection.cpp * Contributed by C. G. Alvarez * sqlSetConnectAttr() and connect() * now supports SQL_ATTR_TXN_ISOLATION @@ -257,7 +257,7 @@ bool moduleInit() if ( fn < 100 ) { // - // SQL_API_ALL_FUNCTIONS is used by an ODBC 2.x application + // SQL_API_ALL_FUNCTIONS is used by an ODBC 2.x application // to determine support of ODBC 2.x and earlier functions // // where functionsArray should be 100 elements @@ -330,18 +330,13 @@ OdbcConnection::OdbcConnection(OdbcEnv *parent) #if _MSC_VER > 1000 enlistConnect = false; #endif // _MSC_VER > 1000 - WcsToMbs = _WcsToMbs; - MbsToWcs = _MbsToWcs; -#else - WcsToMbs = wcstombs; - MbsToWcs = mbstowcs; #endif // _WINDOWS } OdbcConnection::~OdbcConnection() { - releaseObjects(); + releaseObjects(); } void OdbcConnection::releaseObjects() @@ -358,7 +353,7 @@ void OdbcConnection::releaseObjects() statements = (OdbcStatement*)statement->next; delete statement; } - + while ( descriptors ) { OdbcDesc* descriptor = descriptors; @@ -396,8 +391,8 @@ SQLRETURN OdbcConnection::sqlSetConnectAttr( SQLINTEGER attribute, SQLPOINTER va if ( !IsInstalledMsTdsInterface() ) { - return sqlReturn( SQL_ERROR, - "IM001", + return sqlReturn( SQL_ERROR, + "IM001", "Unable start DTC transaction : library 'xolehlp.dll' failed to load" ); } @@ -709,7 +704,7 @@ SQLRETURN OdbcConnection::sqlDriverConnect(SQLHWND hWnd, const SQLCHAR * connect } #ifdef _WINDOWS - if ( driverCompletion != SQL_DRIVER_NOPROMPT + if ( driverCompletion != SQL_DRIVER_NOPROMPT && ( account.IsEmpty() || password.IsEmpty() ) ) { CConnectDialog dlg; @@ -791,8 +786,8 @@ SQLRETURN OdbcConnection::sqlDriverConnect(SQLHWND hWnd, const SQLCHAR * connect return sqlSuccess(); } -SQLRETURN OdbcConnection::sqlBrowseConnect(SQLCHAR * inConnectionString, SQLSMALLINT stringLength1, - SQLCHAR * outConnectionString, SQLSMALLINT bufferLength, +SQLRETURN OdbcConnection::sqlBrowseConnect(SQLCHAR * inConnectionString, SQLSMALLINT stringLength1, + SQLCHAR * outConnectionString, SQLSMALLINT bufferLength, SQLSMALLINT * stringLength2Ptr) { bool bFullConnectionString = false; @@ -1016,7 +1011,7 @@ SQLRETURN OdbcConnection::sqlNativeSql( SQLCHAR * inStatementText, SQLINTEGER te try { - if ( !connection->getNativeSql( (const char *)inStatementText, textLength1, + if ( !connection->getNativeSql( (const char *)inStatementText, textLength1, tempNative.getBuffer ( textLength ), textLength, &textLength ) ) { textLength = textLength1; @@ -1615,7 +1610,6 @@ SQLRETURN OdbcConnection::sqlConnect(const SQLCHAR *dataSetName, int dsnLength, account = getString (&p, uid, uidLength, ""); password = getString (&p, passwd, passwdLength, ""); role = ""; - charset = ""; expandConnectParameters(); SQLRETURN ret = connect (jdbcDriver, databaseName, account, password, role, charset); @@ -1668,8 +1662,8 @@ SQLRETURN OdbcConnection::connect(const char *sharedLibrary, const char * databa properties->putValue ("autoQuoted", autoQuotedIdentifier ? "Y" : "N"); properties->putValue ("databaseAccess", - databaseAccess == CREATE_DB ? "1" - : databaseAccess == DROP_DB ? "2" + databaseAccess == CREATE_DB ? "1" + : databaseAccess == DROP_DB ? "2" : "0"); if (useSchemaIdentifier) @@ -1706,8 +1700,7 @@ SQLRETURN OdbcConnection::connect(const char *sharedLibrary, const char * databa connection->setExtInitTransaction( optTpb ); connection->setUseAppOdbcVersion( env->useAppOdbcVersion ); charsetCode = connection->getConnectionCharsetCode(); - WcsToMbs = connection->getConnectionWcsToMbs(); - MbsToWcs = connection->getConnectionMbsToWcs(); + convert.setCharsetCode(charsetCode); } catch ( std::exception &ex ) { @@ -1842,7 +1835,9 @@ void OdbcConnection::expandConnectParameters() role = readAttribute(SETUP_ROLE); if (charset.IsEmpty()) + { charset = readAttribute(SETUP_CHARSET); + } if ( !(defOptions & DEF_READONLY_TPB) ) { @@ -2098,7 +2093,7 @@ SQLRETURN OdbcConnection::sqlGetConnectAttr(int attribute, SQLPOINTER ptr, int b value = asyncEnabled; break; - case SQL_ATTR_ACCESS_MODE: // 101 + case SQL_ATTR_ACCESS_MODE: // 101 value = accessMode; break; diff --git a/OdbcConnection.h b/OdbcConnection.h index d171610c..76667c73 100644 --- a/OdbcConnection.h +++ b/OdbcConnection.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -30,6 +30,7 @@ #endif #include "OdbcDesc.h" +#include "IscDbc/MultibyteConvert.h" #include "IscDbc/JString.h" #include "Headers/OdbcUserEvents.h" @@ -38,10 +39,10 @@ namespace OdbcJdbcLibrary { class OdbcEnv; class OdbcStatement; -class OdbcConnection : public OdbcObject +class OdbcConnection : public OdbcObject { - enum - { + enum + { DEF_READONLY_TPB = 1, DEF_NOWAIT_TPB = 2, DEF_DIALECT = 4, @@ -73,9 +74,9 @@ class OdbcConnection : public OdbcObject JString readAttribute (const char *attribute); JString readAttributeFileDSN (const char * attribute); void writeAttributeFileDSN (const char * attribute, const char * value); - SQLRETURN sqlDriverConnect (SQLHWND hWnd, - const SQLCHAR *connectString, int connectStringLength, - SQLCHAR *outConnectBuffer, int connectBufferLength, SQLSMALLINT *outStringLength, + SQLRETURN sqlDriverConnect (SQLHWND hWnd, + const SQLCHAR *connectString, int connectStringLength, + SQLCHAR *outConnectBuffer, int connectBufferLength, SQLSMALLINT *outStringLength, int driverCompletion); SQLRETURN sqlBrowseConnect(SQLCHAR * inConnectionString, SQLSMALLINT stringLength1, SQLCHAR * outConnectionString, SQLSMALLINT bufferLength, SQLSMALLINT * stringLength2Ptr); SQLRETURN sqlNativeSql(SQLCHAR * inStatementText, SQLINTEGER textLength1, SQLCHAR * outStatementText, SQLINTEGER bufferLength, SQLINTEGER * textLength2Ptr); @@ -148,8 +149,17 @@ class OdbcConnection : public OdbcObject int statementNumber; int levelBrowseConnect; int charsetCode; - WCSTOMBS WcsToMbs; - MBSTOWCS MbsToWcs; + Convert convert; + + // Connect from SQLWCHAR to connection charset + int fromWcs(const SQLWCHAR* wcs, ssize_t wcsLength, char* str, size_t& strLength) + { + return convert.fromWcs(wcs, wcsLength, str, strLength); + } + int toWcs(const char* str, ssize_t strLength, SQLWCHAR* wcs, size_t& wcsLength) + { + return convert.toWcs(str, strLength, wcs, wcsLength); + } PODBC_USER_EVENTS_INTERFASE userEventsInterfase; diff --git a/OdbcConvert.cpp b/OdbcConvert.cpp index 1f5a8594..2ae87762 100644 --- a/OdbcConvert.cpp +++ b/OdbcConvert.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -62,7 +62,7 @@ #define HI_LONG(l) ((int)(((UQUAD)(l) >> 32) & 0xFFFFFFFF)) #endif -size_t wcscch(const wchar_t* s, size_t len) +size_t wcscch(const SQLWCHAR* s, size_t len) { size_t ret = len; while (len--) @@ -718,7 +718,7 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t return &OdbcConvert::notYetImplemented; } } - else + else { if ( to->isIndicatorSqlDa && to->headSqlVarPtr->isReplaceForParamArray() ) { @@ -836,7 +836,6 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t break; case SQL_C_WCHAR: - if ( from->type == JDBC_VARCHAR || from->type == JDBC_WVARCHAR || from->type == JDBC_LONGVARCHAR || from->type == JDBC_WLONGVARCHAR ) { switch(to->conciseType) // Varying { @@ -882,123 +881,6 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t return &OdbcConvert::notYetImplemented; } } - else - { - if ( to->isIndicatorSqlDa && to->headSqlVarPtr->isReplaceForParamArray() ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferArrayStringToAllowedType; - } - - switch(to->conciseType) // Text - { - case SQL_C_LONG: - case SQL_C_ULONG: - case SQL_C_SLONG: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToLong; - case SQL_C_TINYINT: - case SQL_C_UTINYINT: - case SQL_C_STINYINT: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringToTinyInt; - } - return &OdbcConvert::convStringToTinyInt; - case SQL_C_SHORT: - case SQL_C_USHORT: - case SQL_C_SSHORT: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToShort; - case SQL_C_FLOAT: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToFloat; - case SQL_C_DOUBLE: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToDouble; - case SQL_C_SBIGINT: - case SQL_C_UBIGINT: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToBigint; - case SQL_C_CHAR: - if ( to->type == SQL_VARCHAR || to->type == SQL_LONGVARCHAR ) - { - if ( to->isIndicatorSqlDa ) - { - if ( to->isBlobOrArray ) - return &OdbcConvert::convStringWToBlob; - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToVarString; - } - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToString; - case SQL_C_WCHAR: - if ( to->type == SQL_VARCHAR || to->type == SQL_LONGVARCHAR ) - { - if ( to->isIndicatorSqlDa ) - { - if ( to->isBlobOrArray ) - return &OdbcConvert::convStringWToBlob; - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToAllowedType; - } - return &OdbcConvert::convStringToVarString; - } - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - if ( to->type == JDBC_WVARCHAR || to->type == JDBC_WCHAR ) - return &OdbcConvert::transferStringWToAllowedType; - return &OdbcConvert::transferStringToAllowedType; - } - bIdentity = true; - return &OdbcConvert::convStringToStringW; - case SQL_C_BINARY: - if ( to->isIndicatorSqlDa ) - return &OdbcConvert::convStringWToBlob; - return &OdbcConvert::convStringToString; - case SQL_C_DATE: - case SQL_C_TYPE_DATE: - case SQL_C_TIME: - case SQL_C_TYPE_TIME: - case SQL_C_TYPE_TIMESTAMP: - case SQL_C_TIMESTAMP: - if ( to->isIndicatorSqlDa ) - { - to->headSqlVarPtr->setTypeText(); - return &OdbcConvert::transferStringWToDateTime; - } - default: - return &OdbcConvert::notYetImplemented; - } - } break; case SQL_C_GUID: switch(to->conciseType) @@ -1018,7 +900,7 @@ ADRESS_FUNCTION OdbcConvert::getAdressFunction(DescRecord * from, DescRecord * t return NULL; } -inline +inline SQLPOINTER OdbcConvert::getAdressBindDataFrom(char * pointer) { return pointer ? (SQLPOINTER)(pointer + *bindOffsetPtrFrom) : NULL; @@ -1027,10 +909,10 @@ SQLPOINTER OdbcConvert::getAdressBindDataFrom(char * pointer) inline SQLLEN * OdbcConvert::getAdressBindIndFrom(char * pointer) { - return pointer ? (SQLLEN *)(pointer + *bindOffsetPtrIndFrom) : NULL; + return pointer ? (SQLLEN *)(pointer + *bindOffsetPtrIndFrom) : NULL; } -inline +inline SQLPOINTER OdbcConvert::getAdressBindDataTo(char * pointer) { return pointer ? (SQLPOINTER)(pointer + *bindOffsetPtrTo) : NULL; @@ -1060,7 +942,7 @@ SQLLEN * OdbcConvert::getAdressBindIndTo(char * pointer) if ( indicatorTo ) \ setIndicatorPtr( indicatorTo, SQL_NULL_DATA, to ); \ if ( pointerTo ) \ - *(wchar_t*)pointerTo = 0; \ + *(SQLWCHAR*)pointerTo = 0; \ return SQL_SUCCESS; \ } \ if ( !pointerTo ) \ @@ -1119,12 +1001,12 @@ SQLLEN * OdbcConvert::getAdressBindIndTo(char * pointer) if ( octetLengthPtr ) \ { \ if ( *octetLengthPtr == SQL_NTS ) \ - len = (int)wcslen ( pointerFrom ); \ + len = (int)SQLWCHAR_len ( pointerFrom ); \ else \ len = *octetLengthPtr / 2; \ } \ else \ - len = (int)wcslen( pointerFrom ); \ + len = (int)SQLWCHAR_len( pointerFrom ); \ #define ODBCCONVERT_CONV(TYPE_FROM,C_TYPE_FROM,TYPE_TO,C_TYPE_TO) \ int OdbcConvert::conv##TYPE_FROM##To##TYPE_TO(DescRecord * from, DescRecord * to) \ @@ -1387,22 +1269,23 @@ int OdbcConvert::conv##TYPE_FROM##ToStringW(DescRecord * from, DescRecord * to) int len = to->length; \ \ if ( !len && to->dataPtr) \ - *(char*)to->dataPtr = 0; \ + *(SQLWCHAR*)to->dataPtr = 0; \ else \ { /* Original source from IscDbc/Value.cpp */ \ C_TYPE_FROM number = *(C_TYPE_FROM*)getAdressBindDataFrom((char*)from->dataPtr); \ - char *string = (char*)pointer; \ + SQLWCHAR *string = (SQLWCHAR*)pointer; \ int scale = -from->scale; \ \ if (number == 0) \ { \ - len = 1; \ - strcpy (string, "0"); \ + len = 1 * sizeof(SQLWCHAR); \ + *string++ = '0'; \ + *string++ = '\0'; \ } \ else if (scale < -DEF_SCALE) \ { \ - len = 3; \ - strcpy (string, "***"); \ + len = 3 * sizeof(SQLWCHAR); \ + *string++ = '*'; *string++ = '*'; *string++ = '*'; *string++ = '\0'; \ } \ else \ { \ @@ -1430,27 +1313,19 @@ int OdbcConvert::conv##TYPE_FROM##ToStringW(DescRecord * from, DescRecord * to) *p++ = '.'; \ } \ \ - char *q = string; \ + SQLWCHAR* q = string; \ int l=0; \ \ - if (negative) \ - *q++ = '-',++l; \ + if (negative) { *q++ = '-'; ++l; } \ \ - if ( p - temp > len - l ) \ + if ( p - temp >= (len - l) / sizeof(SQLWCHAR) ) \ p = temp + len - l; \ \ while (p > temp) \ *q++ = *--p; \ \ *q = 0; \ - len = q - string; \ - } \ - { \ - char tempBuf [256]; \ - strcpy( tempBuf, string ); \ - from->MbsToWcs( (wchar_t *)string, tempBuf, len ); \ - ((wchar_t *)string)[len] = L'\0'; \ - len *=2; \ + len = (q - string) * sizeof(SQLWCHAR); \ } \ } \ \ @@ -1629,9 +1504,9 @@ int OdbcConvert::convBlob##To##TYPE_TO(DescRecord * from, DescRecord * to) } \ int OdbcConvert::notYetImplemented(DescRecord * from, DescRecord * to) -{ +{ parentStmt->postError ("07006", "Restricted data type attribute violation"); - return SQL_ERROR; + return SQL_ERROR; } //////////////////////////////////////////////////////////////////////// @@ -1665,19 +1540,36 @@ int OdbcConvert::convGuidToString(DescRecord * from, DescRecord * to) int OdbcConvert::convGuidToStringW(DescRecord * from, DescRecord * to) { - wchar_t *pointer = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR *pointer = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULLW( pointer ); SQLGUID *g = (SQLGUID*)getAdressBindDataFrom((char*)from->dataPtr); - int len, outlen = to->length / sizeof( wchar_t ); + int outlen = to->length / sizeof( SQLWCHAR ); - len = swprintf(pointer, outlen, L"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + char tmp[outlen]; + int len = snprintf(tmp, outlen, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", (unsigned int) g->Data1, g->Data2, g->Data3, g->Data4[0], g->Data4[1], g->Data4[2], g->Data4[3], g->Data4[4], g->Data4[5], g->Data4[6], g->Data4[7]); - len = len == -1 ? outlen * sizeof( wchar_t ) : len * sizeof( wchar_t ); + if (len < 0) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } + + char* p = tmp; + for (int i = 0; i < len; i++) + { + *pointer++ = *p++; + } + *pointer++ = '\0'; + + len *= sizeof(SQLWCHAR); if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); @@ -1782,18 +1674,18 @@ int OdbcConvert::convFloatToString(DescRecord * from, DescRecord * to) int OdbcConvert::convFloatToStringW(DescRecord * from, DescRecord * to) { - wchar_t * pointerTo = (wchar_t *)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointerTo = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN *indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULLW( pointerTo ); - int len = to->length; + int len = to->length / sizeof(SQLWCHAR); if ( len ) { - ConvertFloatToString(*(float*)getAdressBindDataFrom((char*)from->dataPtr), pointerTo, len/2, &len); - len *= sizeof( wchar_t ); + ConvertFloatToString(*(float*)getAdressBindDataFrom((char*)from->dataPtr), pointerTo, len, &len); + len *= sizeof(SQLWCHAR); } if ( to->isIndicatorSqlDa ) { @@ -1889,18 +1781,18 @@ int OdbcConvert::convDoubleToString(DescRecord * from, DescRecord * to) int OdbcConvert::convDoubleToStringW(DescRecord * from, DescRecord * to) { - wchar_t * pointerTo = (wchar_t *)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointerTo = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULLW( pointerTo ); - int len = to->length; + int len = to->length / sizeof(SQLWCHAR); if ( len ) // MAX_DOUBLE_DIGIT_LENGTH = 15 { - ConvertFloatToString(*(double*)getAdressBindDataFrom((char*)from->dataPtr), pointerTo, len/2, &len); - len *= sizeof( wchar_t ); + ConvertFloatToString(*(double*)getAdressBindDataFrom((char*)from->dataPtr), pointerTo, len, &len); + len *= sizeof(SQLWCHAR); } if ( to->isIndicatorSqlDa ) { @@ -2008,7 +1900,7 @@ int OdbcConvert::convDateToString(DescRecord * from, DescRecord * to) int OdbcConvert::convDateToStringW(DescRecord * from, DescRecord * to) { - wchar_t *pointer = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR *pointer = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); @@ -2018,11 +1910,29 @@ int OdbcConvert::convDateToStringW(DescRecord * from, DescRecord * to) SQLSMALLINT year; decode_sql_date(*(int*)getAdressBindDataFrom((char*)from->dataPtr), mday, month, year); - int len, outlen = to->length / sizeof( wchar_t ); + int outlen = to->length / sizeof(SQLWCHAR); + + char tmp[outlen]; + int len = snprintf(tmp, outlen, "%04d-%02d-%02d", year, month, mday); + + if (len < 0) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } - len = swprintf(pointer, outlen, L"%04d-%02d-%02d",year,month,mday); + char* p = tmp; + for (int i = 0; i < len; i++) + { + *pointer++ = *p++; + } + *pointer++ = '\0'; + + len *= sizeof(SQLWCHAR); - len = len == -1 ? outlen * sizeof( wchar_t ) : len * sizeof( wchar_t ); if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); } else @@ -2177,7 +2087,14 @@ int OdbcConvert::convTimeToString(DescRecord * from, DescRecord * to) else len = snprintf(pointer, outlen, "%02d:%02d:%02d",hour, minute, second); - if ( len == -1 ) len = outlen; + if ( len == -1 ) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); @@ -2190,7 +2107,7 @@ int OdbcConvert::convTimeToString(DescRecord * from, DescRecord * to) int OdbcConvert::convTimeToStringW(DescRecord * from, DescRecord * to) { - wchar_t *pointer = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointer = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); @@ -2202,14 +2119,33 @@ int OdbcConvert::convTimeToStringW(DescRecord * from, DescRecord * to) decode_sql_time(ntime, hour, minute, second); - int len, outlen = to->length / sizeof( wchar_t ); + int outlen = to->length / sizeof(SQLWCHAR); + + char tmp[outlen]; + int len; if ( nnano ) - len = swprintf(pointer, outlen, L"%02d:%02d:%02d.%04lu",hour, minute, second, nnano); + len = snprintf(tmp, outlen, "%02d:%02d:%02d.%04lu", hour, minute, second, nnano); else - len = swprintf(pointer, outlen, L"%02d:%02d:%02d",hour, minute, second); + len = snprintf(tmp, outlen, "%02d:%02d:%02d", hour, minute, second); + + if (len < 0) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } + + char* p = tmp; + for (int i = 0; i < len; i++) + { + *pointer++ = *p++; + } + *pointer++ = '\0'; - len = len == -1 ? outlen * sizeof( wchar_t ) : len * sizeof( wchar_t ); + len *= sizeof(SQLWCHAR); if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); @@ -2373,7 +2309,14 @@ int OdbcConvert::convDateTimeToString(DescRecord * from, DescRecord * to) else len = snprintf(pointer, outlen, "%04d-%02d-%02d %02d:%02d:%02d",year,month,mday,hour, minute, second); - if ( len == -1 ) len = outlen; + if (len == -1) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); @@ -2386,7 +2329,7 @@ int OdbcConvert::convDateTimeToString(DescRecord * from, DescRecord * to) int OdbcConvert::convDateTimeToStringW(DescRecord * from, DescRecord * to) { - wchar_t *pointer = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointer = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); @@ -2402,14 +2345,33 @@ int OdbcConvert::convDateTimeToStringW(DescRecord * from, DescRecord * to) decode_sql_date(ndate, mday, month, year); decode_sql_time(ntime, hour, minute, second); - int len, outlen = to->length / sizeof( wchar_t ); + int outlen = to->length / sizeof(SQLWCHAR); + + char tmp[outlen]; + int len; if ( nnano ) - len = swprintf( pointer, outlen, L"%04d-%02d-%02d %02d:%02d:%02d.%04lu",year,month,mday,hour, minute, second, nnano ); + len = snprintf(tmp, outlen, "%04d-%02d-%02d %02d:%02d:%02d.%04lu", year, month, mday, hour, minute, second, nnano); else - len = swprintf( pointer, outlen, L"%04d-%02d-%02d %02d:%02d:%02d",year,month,mday,hour, minute, second ); + len = snprintf(tmp, outlen, "%04d-%02d-%02d %02d:%02d:%02d", year, month, mday, hour, minute, second); - len = len == -1 ? outlen * sizeof( wchar_t ) : len * sizeof( wchar_t ); + if (len == -1) + { + return SQL_ERROR; + } + if (len >= outlen) + { + len = outlen - 1; + } + + char* p = tmp; + for (int i = 0; i < len; i++) + { + *pointer++ = *p++; + } + *pointer++ = '\0'; + + len *= sizeof(SQLWCHAR); if ( to->isIndicatorSqlDa ) { to->headSqlVarPtr->setSqlLen(len); @@ -2469,7 +2431,7 @@ int OdbcConvert::convDateTimeToTagDateTime(DescRecord * from, DescRecord * to) int nday = LO_LONG(number); int ntime = HI_LONG(number); - if ( ntime < 0 ) + if ( ntime < 0 ) ntime = 0; decode_sql_date(nday, tagTs->day, tagTs->month, tagTs->year); @@ -2511,7 +2473,7 @@ int OdbcConvert::convDateTimeToBinary(DescRecord * from, DescRecord * to) decode_sql_time(ntime, tagTs.hour, tagTs.minute, tagTs.second); tagTs.fraction = (ntime % ISC_TIME_SECONDS_PRECISION); - if ( tagTs.fraction ) + if ( tagTs.fraction ) tagTs.fraction = (10000 + tagTs.fraction) / 100 - 100; shortDate *ptd = (shortDate*)pointer; @@ -2657,16 +2619,16 @@ int OdbcConvert::convBlobToBlob(DescRecord * from, DescRecord * to) from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length)); int lenRead; - + if ( pointer ) { - if ( len > 0 ) + if ( len > 0 ) { if ( blob->isArray() ) blob->getBinary (from->dataOffset, len, pointer); else if ( directOpen ) blob->directFetchBlob((char*)pointer, len, lenRead); - else + else blob->getBytes (from->dataOffset, len, pointer); } @@ -2745,8 +2707,8 @@ int OdbcConvert::convBlobToBinary(DescRecord * from, DescRecord * to) from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length-1)>>1); int lenRead; - - if ( len > 0 ) + + if ( len > 0 ) { if ( directOpen ) blob->directFetchBlob((char*)pointer, len, lenRead); @@ -2821,7 +2783,7 @@ int OdbcConvert::convBlobToString(DescRecord * from, DescRecord * to) else { length = blob->length(); - + if ( blob->isBlob() ) length *= 2; } @@ -2840,10 +2802,10 @@ int OdbcConvert::convBlobToString(DescRecord * from, DescRecord * to) from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length-1)); int lenRead; - + if ( pointer ) { - if ( len > 0 ) + if ( len > 0 ) { if ( !directOpen ) { @@ -2940,32 +2902,18 @@ int OdbcConvert::convBlobToStringW( DescRecord * from, DescRecord * to ) else length = blob->length(); - from->allocateLocalDataPtr((length + 1) * sizeof(wchar_t)); - wchar_t *wcs = (wchar_t*) from->localDataPtr; + from->allocateLocalDataPtr((length + 1) * sizeof(SQLWCHAR)); + SQLWCHAR *wcs = (SQLWCHAR*) from->localDataPtr; if (length) { - char* tmp = new char[length]; - - if (!directOpen) - { - blob->getBytes(0, length, tmp); - } - else - { - int lenRead = 0; - blob->directFetchBlob(tmp, length, lenRead); - length = lenRead; - } - - length = from->MbsToWcs(wcs, tmp, length); - delete[] tmp; + blob->getBytesW(0, length, wcs); } wcs[length] = L'\0'; } else { - length = wcslen(((wchar_t*) from->localDataPtr) + from->dataOffset) + from->dataOffset; + length = SQLWCHAR_len(reinterpret_cast(from->localDataPtr) + from->dataOffset) + from->dataOffset; } dataRemaining = length - from->dataOffset; @@ -2980,14 +2928,14 @@ int OdbcConvert::convBlobToStringW( DescRecord * from, DescRecord * to ) else { from->startedReturnSQLData = true; - int len = MIN(dataRemaining, MAX(0, to->length / (int)sizeof(wchar_t) - 1)); - + int len = MIN(dataRemaining, MAX(0, to->length / (int)sizeof(SQLWCHAR) - 1)); + if ( pointer ) { if (blob->isBlob()) { len &= ~1; // we can only return an even number - if ( len > 0 ) + if ( len > 0 ) { char *tmp = new char[len]; @@ -3002,17 +2950,25 @@ int OdbcConvert::convBlobToStringW( DescRecord * from, DescRecord * to ) len = lenRead; } - from->MbsToWcs( (wchar_t *)pointer, tmp, len ); - - delete [] tmp; + SQLWCHAR* p = (SQLWCHAR*)pointer; + char* q = tmp; + for (int i = 0; i < len; i++) + { + *p++ = *q++; + } } } else { - wcsncpy((wchar_t*) pointer, ((wchar_t*) from->localDataPtr) + from->dataOffset, len); + SQLWCHAR* p = (SQLWCHAR*)pointer; + SQLWCHAR* q = ((SQLWCHAR*) from->localDataPtr) + from->dataOffset; + for (int i = 0; i < len; i++) + { + *p++ = *q++; + } } - ((wchar_t *) (pointer)) [len] = L'\0'; + ((SQLWCHAR*) (pointer)) [len] = '\0'; if ( !statusReturnData ) from->dataOffset += len; @@ -3030,10 +2986,10 @@ int OdbcConvert::convBlobToStringW( DescRecord * from, DescRecord * to ) } if ( to->isIndicatorSqlDa ) { - to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof(wchar_t)); + to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof(SQLWCHAR)); } else if ( indicatorTo ) - setIndicatorPtr(indicatorTo, dataRemaining * sizeof(wchar_t), to); + setIndicatorPtr(indicatorTo, dataRemaining * sizeof(SQLWCHAR), to); return ret; } @@ -3059,7 +3015,7 @@ int OdbcConvert::convBinaryToBlob(DescRecord * from, DescRecord * to) if( len > 0 ) { Blob *& blob = to->dataBlobPtr; - + if ( blob->isArray() ) { blob->clear(); @@ -3156,8 +3112,8 @@ int OdbcConvert::conv##TYPE_FROM##To##TYPE_TO(DescRecord * from, DescRecord * to double divisor = 1; \ bool decimal = false; \ bool negative = false; \ - char *p = (char*)getAdressBindDataFrom((char*)from->dataPtr + OFFSET_STRING), \ - *end = p + CALC_LEN_STRING; \ + SQLWCHAR *p = (SQLWCHAR*)getAdressBindDataFrom((char*)from->dataPtr + OFFSET_STRING); \ + SQLWCHAR *end = p + SQLWCHAR_len(p); \ for (;p < end; ++p ) \ { \ char c = *p++; \ @@ -3244,7 +3200,7 @@ int OdbcConvert::convStringToString(DescRecord * from, DescRecord * to) { from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length-1)); - + if ( !pointerTo ) length = dataRemaining; else @@ -3262,7 +3218,7 @@ int OdbcConvert::convStringToString(DescRecord * from, DescRecord * to) OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); ret = SQL_SUCCESS_WITH_INFO; } - + length = dataRemaining; } } @@ -3279,8 +3235,8 @@ int OdbcConvert::convStringToString(DescRecord * from, DescRecord * to) int OdbcConvert::convStringToStringW(DescRecord * from, DescRecord * to) { char * pointerFrom = (char*)getAdressBindDataFrom((char*)from->dataPtr); - wchar_t * pointerFromWcs; - wchar_t * pointerTo = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointerFromWcs; + SQLWCHAR* pointerTo = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); @@ -3297,24 +3253,22 @@ int OdbcConvert::convStringToStringW(DescRecord * from, DescRecord * to) from->currentFetched = parentStmt->getCurrentFetched(); if (!to->isLocalDataPtr) - to->allocateLocalDataPtr((from->getBufferLength() + 1) * sizeof(wchar_t)); + to->allocateLocalDataPtr((from->getBufferLength() + 1) * sizeof(SQLWCHAR)); - pointerFromWcs = (wchar_t*) to->localDataPtr; + pointerFromWcs = (SQLWCHAR*) to->localDataPtr; - length = (int)from->MbsToWcs( pointerFromWcs, pointerFrom, from->length * from->headSqlVarPtr->getSqlMultiple() ); - if ( length < 0 ) - length = 0; - - while (length < from->length) // safety-code - should not happen - pointerFromWcs[length++] = L' '; - - length = from->length; - pointerFromWcs[length] = L'\0'; + Convert conv; + size_t l = from->getBufferLength() + 1; + if (conv.toWcs( pointerFrom, from->length * from->headSqlVarPtr->getSqlMultiple(), pointerFromWcs, l ) != 0) + { + //ret = SQL_ERROR; ??? + } + length = l; } else { - pointerFromWcs = (wchar_t*) to->localDataPtr; - length = wcslen(pointerFromWcs + from->dataOffset) + from->dataOffset; + pointerFromWcs = (SQLWCHAR*) to->localDataPtr; + length = SQLWCHAR_len(pointerFromWcs + from->dataOffset) + from->dataOffset; } int dataRemaining = length - from->dataOffset; @@ -3329,11 +3283,16 @@ int OdbcConvert::convStringToStringW(DescRecord * from, DescRecord * to) else { from->startedReturnSQLData = true; - int len = MIN(dataRemaining, MAX(0, (int)(to->length / sizeof( wchar_t )) - 1 )); - + int len = MIN(dataRemaining, MAX(0, (int)(to->length / sizeof( SQLWCHAR )) - 1 )); + if ( pointerTo ) { - wcsncpy(pointerTo, pointerFromWcs + from->dataOffset, len); + SQLWCHAR* p = pointerTo; + SQLWCHAR* q = pointerFromWcs + from->dataOffset; + for (int i = 0; i < len; i++) + { + *p++ = *q++; + } pointerTo[len] = L'\0'; from->dataOffset += len; @@ -3347,17 +3306,17 @@ int OdbcConvert::convStringToStringW(DescRecord * from, DescRecord * to) } if ( to->isIndicatorSqlDa ) { - to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof( wchar_t )); + to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof(SQLWCHAR)); } else if ( indicatorTo ) - setIndicatorPtr(indicatorTo, dataRemaining * sizeof(wchar_t), to); + setIndicatorPtr(indicatorTo, dataRemaining * sizeof(SQLWCHAR), to); return ret; } // for use App to SqlDa int OdbcConvert::convStringToVarString(DescRecord * from, DescRecord * to) -{ +{ SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); @@ -3397,7 +3356,7 @@ int OdbcConvert::convStringToVarString(DescRecord * from, DescRecord * to) // for use App to SqlDa int OdbcConvert::convStringToBlob(DescRecord * from, DescRecord * to) -{ +{ SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); @@ -3416,7 +3375,7 @@ int OdbcConvert::convStringToBlob(DescRecord * from, DescRecord * to) if( len > 0 ) to->dataBlobPtr->writeStringHexToBlob(pointerTo, pointerFrom, len); - else + else setIndicatorPtr(indicatorTo, SQL_NULL_DATA, to); return ret; @@ -3424,14 +3383,14 @@ int OdbcConvert::convStringToBlob(DescRecord * from, DescRecord * to) // for use App to SqlDa int OdbcConvert::convStringWToBlob(DescRecord * from, DescRecord * to) -{ +{ SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); ODBCCONVERT_CHECKNULL_SQLDA; SQLLEN * octetLengthPtr = getAdressBindIndFrom((char*)from->octetLengthPtr); - wchar_t * pointerFrom = (wchar_t*)getAdressBindDataFrom((char*)from->dataPtr); + SQLWCHAR* pointerFrom = (SQLWCHAR*)getAdressBindDataFrom((char*)from->dataPtr); char * pointerTo = (char*)getAdressBindDataTo((char*)to->dataPtr); SQLINTEGER len; @@ -3440,17 +3399,24 @@ int OdbcConvert::convStringWToBlob(DescRecord * from, DescRecord * to) GET_WLEN_FROM_OCTETLENGTHPTR; - lenMbs = (SQLUINTEGER)to->WcsToMbs( NULL, pointerFrom, 0 ); - lenMbs = MIN( lenMbs, (int)MAX(0, (int)to->length)); + // This routine seems to work only with hex string so there is no point for + // full Mbs conversion. + len = MIN( len, (int)MAX(0, (int)to->length)); - if ( lenMbs > 0 ) + if ( len > 0 ) { - char* tempValue = new char[lenMbs + 1]; - lenMbs = (SQLUINTEGER)to->WcsToMbs( tempValue, pointerFrom, lenMbs ); - to->dataBlobPtr->writeStringHexToBlob(pointerTo, tempValue, lenMbs); + char* tempValue = new char[len + 1]; + const SQLWCHAR* p = pointerFrom; + char* q = tempValue; + for (int i = 0; i < len; i++) + { + *q++ = *p++; + } + *q = '\0'; + to->dataBlobPtr->writeStringHexToBlob(pointerTo, tempValue, len); delete [] tempValue; } - else + else setIndicatorPtr(indicatorTo, SQL_NULL_DATA, to); return ret; @@ -3458,7 +3424,7 @@ int OdbcConvert::convStringWToBlob(DescRecord * from, DescRecord * to) // for use App to SqlDa int OdbcConvert::convStreamHexStringToBlob(DescRecord * from, DescRecord * to) -{ +{ char * pointerTo = (char*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); @@ -3477,7 +3443,7 @@ int OdbcConvert::convStreamHexStringToBlob(DescRecord * from, DescRecord * to) // for use App to SqlDa int OdbcConvert::convStreamToBlob(DescRecord * from, DescRecord * to) -{ +{ char * pointerTo = (char*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); @@ -3522,7 +3488,7 @@ int OdbcConvert::convStringToBinary(DescRecord * from, DescRecord * to) { from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length)); - + if ( !pointerTo ) length = dataRemaining; else @@ -3538,7 +3504,7 @@ int OdbcConvert::convStringToBinary(DescRecord * from, DescRecord * to) OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); ret = SQL_SUCCESS_WITH_INFO; } - + length = dataRemaining; } } @@ -3585,7 +3551,7 @@ int OdbcConvert::transferStringToTinyInt(DescRecord * from, DescRecord * to) src++; minus = true; } - + while ( *src ) { val *= 10; @@ -3646,7 +3612,7 @@ int OdbcConvert::transferStringWToDateTime(DescRecord * from, DescRecord * to) ODBCCONVERT_CHECKNULL_SQLDA; SQLLEN * octetLengthPtr = getAdressBindIndFrom((char*)from->octetLengthPtr); - wchar_t * pointerFrom = (wchar_t*)getAdressBindDataFrom((char*)from->dataPtr); + SQLWCHAR* pointerFrom = (SQLWCHAR*)getAdressBindDataFrom((char*)from->dataPtr); int len = 0; @@ -3656,9 +3622,10 @@ int OdbcConvert::transferStringWToDateTime(DescRecord * from, DescRecord * to) GET_WLEN_FROM_OCTETLENGTHPTR int n = len; + // Really? This code will fail miserably on big-endian platforms. char * beg = (char*)pointerFrom + 1; short * next = (short*)(beg + 1); - + while ( n-- ) *beg++ = (char)*next++; @@ -3736,73 +3703,6 @@ int OdbcConvert::transferStringToAllowedType(DescRecord * from, DescRecord * to) return ret; } -// for use App to SqlDa -int OdbcConvert::transferStringWToAllowedType(DescRecord * from, DescRecord * to) -{ - SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); - SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); - - ODBCCONVERT_CHECKNULL_SQLDA; - - SQLLEN * octetLengthPtr = getAdressBindIndFrom((char*)from->octetLengthPtr); - wchar_t * pointerFrom = (wchar_t *)getAdressBindDataFrom((char*)from->dataPtr); - - SQLINTEGER len; - SQLINTEGER cch; - SQLINTEGER lenMbs; - SQLRETURN ret = SQL_SUCCESS; - - GET_WLEN_FROM_OCTETLENGTHPTR; - cch = wcscch(pointerFrom, len); - - if ( !to->isLocalDataPtr ) - { - to->allocateLocalDataPtr(); - to->headSqlVarPtr->setSqlData( to->localDataPtr ); - } - - if (from->dataOffset == 0) - to->dataOffset = 0; - - if ( cch + from->dataOffset > to->octetLength ) - { - OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); - ret = SQL_SUCCESS_WITH_INFO; - do - { - len--; - if (!IS_LOW_SURROGATE(pointerFrom[len-1])) - cch--; - } while (cch + from->dataOffset > to->octetLength); - } - - if ( len < 0 ) - { - cch = len = 0; - lenMbs = 0; - } - else - { - wchar_t &wcEnd = *(pointerFrom + len); - wchar_t saveEnd = wcEnd; - wcEnd = L'\0'; // We guarantee the end L'\0' - SQLUINTEGER spaceLeft = (to->octetLength - from->dataOffset) * to->headSqlVarPtr->getSqlMultiple(); - lenMbs = (SQLUINTEGER)to->WcsToMbs( to->localDataPtr + to->dataOffset, pointerFrom, spaceLeft); - wcEnd = saveEnd; - } - - if ( from->data_at_exec ) - { - from->dataOffset += cch; - to->dataOffset += lenMbs; - to->headSqlVarPtr->setSqlLen( (short)to->dataOffset ); - } - else - to->headSqlVarPtr->setSqlLen( (short)lenMbs ); - - return ret; -} - // for use App to SqlDa int OdbcConvert::transferArrayStringToAllowedType(DescRecord * from, DescRecord * to) { @@ -3925,7 +3825,7 @@ int OdbcConvert::convVarStringToBinary(DescRecord * from, DescRecord * to) { from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length)); - + if ( !pointerTo ) length = dataRemaining; else @@ -3942,7 +3842,7 @@ int OdbcConvert::convVarStringToBinary(DescRecord * from, DescRecord * to) OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); ret = SQL_SUCCESS_WITH_INFO; } - + length = dataRemaining; } } @@ -3989,7 +3889,7 @@ int OdbcConvert::convVarStringToString(DescRecord * from, DescRecord * to) { from->startedReturnSQLData = true; int len = MIN(dataRemaining, MAX(0, (int)to->length-1)); - + if ( !pointerTo ) length = dataRemaining; else @@ -4008,7 +3908,7 @@ int OdbcConvert::convVarStringToString(DescRecord * from, DescRecord * to) OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); ret = SQL_SUCCESS_WITH_INFO; } - + length = dataRemaining; } } @@ -4026,15 +3926,15 @@ int OdbcConvert::convVarStringToStringW(DescRecord * from, DescRecord * to) { short * pointerFromLen = (short*)getAdressBindDataFrom((char*)from->dataPtr); char * pointerFrom = (char*)(pointerFromLen + 1); - wchar_t * pointerFromWcs; - wchar_t * pointerTo = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR* pointerFromWcs; + SQLWCHAR* pointerTo = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULLW( pointerTo ); SQLRETURN ret = SQL_SUCCESS; - int length; + size_t length; bool fetched = from->currentFetched == parentStmt->getCurrentFetched(); if ( !fetched ) @@ -4043,20 +3943,20 @@ int OdbcConvert::convVarStringToStringW(DescRecord * from, DescRecord * to) from->startedReturnSQLData = false; from->currentFetched = parentStmt->getCurrentFetched(); + length = from->getBufferLength() + 1; + if (!to->isLocalDataPtr) - to->allocateLocalDataPtr((from->getBufferLength() + 1) * sizeof(wchar_t)); + to->allocateLocalDataPtr((length) * sizeof(SQLWCHAR)); - pointerFromWcs = (wchar_t*) to->localDataPtr; + pointerFromWcs = (SQLWCHAR*) to->localDataPtr; - length = (int)from->MbsToWcs( pointerFromWcs, pointerFrom, *pointerFromLen ); - if ( length < 0 ) - length = 0; - pointerFromWcs[length] = L'\0'; + Convert conv; + conv.toWcs(pointerFrom, *pointerFromLen, pointerFromWcs, length); } else { - pointerFromWcs = (wchar_t*) to->localDataPtr; - length = wcslen(pointerFromWcs + from->dataOffset) + from->dataOffset; + pointerFromWcs = (SQLWCHAR*) to->localDataPtr; + length = SQLWCHAR_len(pointerFromWcs + from->dataOffset) + from->dataOffset; } int dataRemaining = length - from->dataOffset; @@ -4071,11 +3971,16 @@ int OdbcConvert::convVarStringToStringW(DescRecord * from, DescRecord * to) else { from->startedReturnSQLData = true; - int len = MIN(dataRemaining, MAX(0, (int)(to->length / sizeof( wchar_t )) - 1 )); - + int len = MIN(dataRemaining, MAX(0, (int)(to->length / sizeof(SQLWCHAR)) - 1 )); + if ( pointerTo ) { - wcsncpy(pointerTo, pointerFromWcs + from->dataOffset, len); + SQLWCHAR* p = pointerFromWcs + from->dataOffset; + SQLWCHAR* q = pointerTo; + for (int i = 0; i < len; i++) + { + *q++ = *p++; + } pointerTo[len] = L'\0'; from->dataOffset += len; @@ -4089,10 +3994,10 @@ int OdbcConvert::convVarStringToStringW(DescRecord * from, DescRecord * to) } if ( to->isIndicatorSqlDa ) { - to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof( wchar_t )); + to->headSqlVarPtr->setSqlLen(dataRemaining * sizeof(SQLWCHAR)); } else if ( indicatorTo ) - setIndicatorPtr(indicatorTo, dataRemaining * sizeof(wchar_t), to); + setIndicatorPtr(indicatorTo, dataRemaining * sizeof(SQLWCHAR), to); return ret; } @@ -4105,7 +4010,7 @@ int OdbcConvert::convVarStringSystemToString(DescRecord * from, DescRecord * to) SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULL( pointerTo ); - + SQLRETURN ret = SQL_SUCCESS; unsigned short lenVar = *(unsigned short*)pointerFrom; int len; @@ -4143,30 +4048,35 @@ int OdbcConvert::convVarStringSystemToString(DescRecord * from, DescRecord * to) int OdbcConvert::convVarStringSystemToStringW(DescRecord * from, DescRecord * to) { char *pointerFrom = (char*)getAdressBindDataFrom((char*)from->dataPtr); - wchar_t *pointerTo = (wchar_t*)getAdressBindDataTo((char*)to->dataPtr); + SQLWCHAR *pointerTo = (SQLWCHAR*)getAdressBindDataTo((char*)to->dataPtr); SQLLEN * indicatorTo = getAdressBindIndTo((char*)to->indicatorPtr); SQLLEN * indicatorFrom = getAdressBindIndFrom((char*)from->indicatorPtr); ODBCCONVERT_CHECKNULLW( pointerTo ); - + SQLRETURN ret = SQL_SUCCESS; unsigned short lenVar = *(unsigned short*)pointerFrom; - int len; + SQLINTEGER len; char * src = pointerFrom + 2, * end = src + lenVar; while ( lenVar-- && *(--end) == ' '); len = end - src + 1; - len = MIN( len, MAX(0,(int)(to->length / sizeof( wchar_t )) - 1 )); if( len > 0 ) - mbstowcs( pointerTo, src, len ); - - pointerTo[len] = (wchar_t)'\0'; - len *= sizeof( wchar_t ); + { + size_t length = to->length / sizeof(SQLWCHAR); + Convert conv; + conv.toWcs(src, len, pointerTo, length); + len = length *= sizeof(SQLWCHAR); + } + else + { + pointerTo[len] = '\0'; + } - if (len && (int)len > (int)to->length) + if (len && len > to->length) { OdbcError *error = parentStmt->postError (new OdbcError (0, "01004", "Data truncated")); // if (error) @@ -4209,9 +4119,9 @@ signed int OdbcConvert::encode_sql_date(SQLUSMALLINT day, SQLUSMALLINT month, SQ c = year / 100; ya = year - 100 * c; - return (signed int) (((QUAD) 146097 * c) / 4 + - (1461 * ya) / 4 + - (153 * month + 2) / 5 + + return (signed int) (((QUAD) 146097 * c) / 4 + + (1461 * ya) / 4 + + (153 * month + 2) / 5 + day - 678882); // day + 1721119 - 2400001); } @@ -4325,7 +4235,7 @@ void OdbcConvert::convertStringDateTimeToServerStringDateTime (char *& string, i else { while( *++ptBeg == ' ' ); - + if ( UPPER(*ptBeg) == 'D' ) { offsetPoint = 0; @@ -4387,7 +4297,7 @@ void OdbcConvert::getFirstElementFromArrayString(char * string, char *& firstCha if ( !ptTmp || !*ptTmp ) return; - while( *ptTmp == '{' || *ptTmp == ' ' ) + while( *ptTmp == '{' || *ptTmp == ' ' ) ptTmp++; if ( *ptTmp == '\'' ) diff --git a/OdbcConvert.h b/OdbcConvert.h index 16618b83..d6bfce27 100644 --- a/OdbcConvert.h +++ b/OdbcConvert.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -279,7 +279,6 @@ class OdbcConvert int transferStringToDateTime(DescRecord * from, DescRecord * to); int transferStringWToDateTime(DescRecord * from, DescRecord * to); int transferStringToAllowedType(DescRecord * from, DescRecord * to); - int transferStringWToAllowedType(DescRecord * from, DescRecord * to); int transferArrayStringToAllowedType(DescRecord * from, DescRecord * to); int transferBinaryStringToAllowedType(DescRecord * from, DescRecord * to); int convStreamHexStringToBlob(DescRecord * from, DescRecord * to); diff --git a/OdbcDesc.cpp b/OdbcDesc.cpp index fcd51e1f..de63e16d 100644 --- a/OdbcDesc.cpp +++ b/OdbcDesc.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -112,7 +112,7 @@ void OdbcDesc::removeRecords() headCount = 0; recordSlots = 0; } - + void OdbcDesc::releasePrepared() { if (records) @@ -125,7 +125,7 @@ void OdbcDesc::releasePrepared() } } } - + void OdbcDesc::clearPrepared() { if (records) @@ -140,7 +140,7 @@ void OdbcDesc::clearPrepared() } } } - + void OdbcDesc::updateDefinedIn() { if (records) @@ -156,7 +156,7 @@ void OdbcDesc::updateDefinedIn() } } } - + void OdbcDesc::updateDefinedOut() { if (records) @@ -265,8 +265,6 @@ void OdbcDesc::defFromMetaDataIn(int recNumber, DescRecord * record) record->unNamed = !record->name.IsEmpty() ? SQL_NAMED : SQL_UNNAMED; record->unSigned = SQL_FALSE; record->updaTable = SQL_ATTR_WRITE; - record->MbsToWcs = metaDataIn->getAdressMbsToWcs( recNumber ); - record->WcsToMbs = metaDataIn->getAdressWcsToMbs( recNumber ); record->isDefined = true; record->isBlobOrArray = metaDataIn->isBlobOrArray (recNumber); @@ -308,8 +306,6 @@ void OdbcDesc::defFromMetaDataOut(int recNumber, DescRecord * record) record->unNamed = !record->name.IsEmpty() ? SQL_NAMED : SQL_UNNAMED; record->unSigned = SQL_FALSE; record->updaTable = SQL_ATTR_WRITE; - record->MbsToWcs = metaDataOut->getAdressMbsToWcs( recNumber ); - record->WcsToMbs = metaDataOut->getAdressWcsToMbs( recNumber ); record->isDefined = true; metaDataOut->getSqlData(recNumber, record->dataBlobPtr, record->headSqlVarPtr); @@ -632,15 +628,15 @@ SQLRETURN OdbcDesc::sqlGetDescField(int recNumber, int fieldId, SQLPOINTER ptr, case SQL_DESC_NUM_PREC_RADIX: if (record && ptr) *(SQLINTEGER*) ptr = record->numPrecRadix, - size = sizeof (SQLINTEGER); + size = sizeof (SQLINTEGER); break; - + case SQL_DESC_OCTET_LENGTH: if (record && ptr) *(SQLINTEGER*) ptr = record->octetLength, - size = sizeof (SQLINTEGER); + size = sizeof (SQLINTEGER); break; - + case SQL_DESC_OCTET_LENGTH_PTR: switch(headType) { @@ -856,7 +852,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value i=0; sprintf(strTmp,"\tid %4i - %s : recNumber %i : value %i\n",fieldId,debSetDescField[i].name, recNumber, value ? (intptr_t)value : 0); - OutputDebugString(strTmp); + OutputDebugString(strTmp); #endif clearErrors(); DescRecord *record = NULL; @@ -1056,7 +1052,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value { record->octetLength = (intptr_t)value; record->sizeColumnExtendedFetch = (intptr_t)value; - if ( !record->length ) + if ( !record->length ) record->length = (intptr_t)value; } break; @@ -1067,7 +1063,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value case SQL_DESC_OCTET_LENGTH_PTR: switch(headType) - { + { case odtApplication: case odtApplicationRow: case odtApplicationParameter: @@ -1078,7 +1074,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value return sqlReturn (SQL_ERROR, "HY091", "Invalid descriptor field identifier"); } break; - + case SQL_DESC_PARAMETER_TYPE: if(headType == odtImplementationParameter) { @@ -1121,7 +1117,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value case SQL_DESC_INDICATOR_PTR: switch(headType) - { + { case odtApplication: case odtApplicationRow: case odtApplicationParameter: @@ -1142,7 +1138,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value else return sqlReturn (SQL_ERROR, "HY091", "Invalid descriptor field identifier"); break; - + case SQL_DESC_DATA_PTR: #pragma FB_COMPILER_MESSAGE("Consistency Checks ( help fn. SQLSetDescRec ) FIXME!") switch(headType) @@ -1151,7 +1147,7 @@ SQLRETURN OdbcDesc::sqlSetDescField(int recNumber, int fieldId, SQLPOINTER value case odtApplicationRow: case odtApplicationParameter: if (record) - { // help fn. SQLSetDescRec + { // help fn. SQLSetDescRec record->dataPtr = value; record->isDefined = true; record->isPrepared = false; @@ -1177,15 +1173,15 @@ void OdbcDesc::allocBookmarkField() getDescRecord(0); } -SQLRETURN OdbcDesc::sqlGetDescRec( SQLSMALLINT recNumber, - SQLCHAR *name, +SQLRETURN OdbcDesc::sqlGetDescRec( SQLSMALLINT recNumber, + SQLCHAR *name, SQLSMALLINT bufferLength, - SQLSMALLINT *stringLengthPtr, - SQLSMALLINT *typePtr, - SQLSMALLINT *subTypePtr, - SQLLEN *lengthPtr, - SQLSMALLINT *precisionPtr, - SQLSMALLINT *scalePtr, + SQLSMALLINT *stringLengthPtr, + SQLSMALLINT *typePtr, + SQLSMALLINT *subTypePtr, + SQLLEN *lengthPtr, + SQLSMALLINT *precisionPtr, + SQLSMALLINT *scalePtr, SQLSMALLINT *nullablePtr) { SQLRETURN rc; @@ -1295,7 +1291,7 @@ int OdbcDesc::getConciseType(int type) case JDBC_BOOLEAN: return SQL_C_BIT; - + case JDBC_TINYINT: return SQL_C_STINYINT; diff --git a/OdbcJdbc.h b/OdbcJdbc.h index 32b1f9a4..dd174d70 100644 --- a/OdbcJdbc.h +++ b/OdbcJdbc.h @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -40,7 +40,7 @@ #define OutputDebugString(string) fputs (string, stdout) #endif -#ifdef DEBUG +#ifdef DEBUG #define LOG_MSG(msg) OutputDebugString( msg ) @@ -52,6 +52,9 @@ #define LOG_FILE "/tmp/odbcjdbc.log" #endif +#include +extern FILE* logFile; + #define LOG_PRINT(msg) \ { \ if ( !logFile ) \ diff --git a/OdbcStatement.cpp b/OdbcStatement.cpp index 8c43696d..4bafc526 100644 --- a/OdbcStatement.cpp +++ b/OdbcStatement.cpp @@ -1,14 +1,14 @@ /* - * - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at + * + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. * - * Software distributed under the License is distributed on - * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the License for the specific + * Software distributed under the License is distributed on + * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the License for the specific * language governing rights and limitations under the License. * * @@ -30,7 +30,7 @@ * * 2003-03-24 OdbcStatement.cpp * Contributed by Carlos Guzman Alvarez - * Remove updatePreparedResultSet from OdbStatement + * Remove updatePreparedResultSet from OdbStatement * and achieve the same goal in another way. * * 2003-03-24 OdbcStatement.cpp @@ -61,11 +61,11 @@ * * 2002-08-12 OdbcStatement.cpp * Added changes from C. G. Alvarez to so that - * sqlColAttributes() called with SQL_COLUMN_TYPE_NAME returns + * sqlColAttributes() called with SQL_COLUMN_TYPE_NAME returns * the name of the type instead of the number of the type. - * Similarly, sqlColAttribute() will return string for + * Similarly, sqlColAttribute() will return string for * SQL_DESC_TYPE_NAME. - * + * * Added sqlTablePrivileges() * * @@ -75,7 +75,7 @@ * from sqlColAtrributes() * * 2002-06-26 OdbcStatement.cpp - * Added changes from C. G. Alvarez to provide + * Added changes from C. G. Alvarez to provide * better support for remote views. * * 2002-06-26 OdbcStatement::OdbcStatement @@ -89,33 +89,33 @@ * 2002-06-08 OdbcStatement.cpp * Submitted by B. Schulte * sqlNumResultCols(). - * This fixes the bug : ' I can't edit my remote-views - * in Visual FoxPro'. If the resultSet does not exist, - * execute it, to get a valid resultSet. Foxpro calls - * this function to get all column-descriptions for - * its remote-views. + * This fixes the bug : ' I can't edit my remote-views + * in Visual FoxPro'. If the resultSet does not exist, + * execute it, to get a valid resultSet. Foxpro calls + * this function to get all column-descriptions for + * its remote-views. * * 2002-06-04 OdbcdStatement.cpp * submitted by Robert Milharcic - * Extensive changes to improve writing and + * Extensive changes to improve writing and * retrieval of binary blobs * - * 2002-05-20 Updated OdbcStatement.cpp + * 2002-05-20 Updated OdbcStatement.cpp * * Contributed by Pier Alberto GUIDOTTI - * o Use RM's changes to support reading + * o Use RM's changes to support reading * text blobs too. * - * 2002-05-20 Updated OdbcStatement.cpp + * 2002-05-20 Updated OdbcStatement.cpp * * Contributed by Robert Milharcic * o Several changes to allow reading of binary blobs * See code commented with //Added by RM or //From RM * * - * 2002-05-20 Updated OdbcStatement.cpp + * 2002-05-20 Updated OdbcStatement.cpp * - * Contributed by Bernhard Schulte + * Contributed by Bernhard Schulte * o Use TimeStamp instead of DateTime in setParameter(). * * @@ -139,11 +139,11 @@ #include "OdbcError.h" #include "DescRecord.h" -#ifdef DEBUG +#ifdef DEBUG #define TRACE(msg) OutputDebugString(#msg"\n"); #define TRACE02(msg,val) TraceOutput(#msg,val) #else -#define TRACE(msg) +#define TRACE(msg) #define TRACE02(msg,val) #endif @@ -179,7 +179,7 @@ OdbcStatement::OdbcStatement(OdbcConnection *connect, int statementNumber) cancel = false; countFetched = 0l; enFetch = NoneFetch; - parameterNeedData = 0; + parameterNeedData = 0; maxRows = 0; maxLength = 0; applicationRowDescriptor = connection->allocDescriptor (odtApplicationRow); @@ -251,8 +251,8 @@ OdbcObjectType OdbcStatement::getType() } inline StatementMetaData* OdbcStatement::getStatementMetaDataIRD() -{ - return resultSet ? resultSet->getMetaData() : statement->getStatementMetaDataIRD(); +{ + return resultSet ? resultSet->getMetaData() : statement->getStatementMetaDataIRD(); } inline void OdbcStatement::clearErrors() @@ -261,9 +261,9 @@ inline void OdbcStatement::clearErrors() OdbcObject::clearErrors(); } -SQLRETURN OdbcStatement::sqlTables(SQLCHAR * catalog, int catLength, - SQLCHAR * schema, int schemaLength, - SQLCHAR * table, int tableLength, +SQLRETURN OdbcStatement::sqlTables(SQLCHAR * catalog, int catLength, + SQLCHAR * schema, int schemaLength, + SQLCHAR * table, int tableLength, SQLCHAR * type, int typeLength) { clearErrors(); @@ -312,8 +312,8 @@ SQLRETURN OdbcStatement::sqlTables(SQLCHAR * catalog, int catLength, return sqlSuccess(); } -SQLRETURN OdbcStatement::sqlTablePrivileges(SQLCHAR * catalog, int catLength, - SQLCHAR * schema, int schemaLength, +SQLRETURN OdbcStatement::sqlTablePrivileges(SQLCHAR * catalog, int catLength, + SQLCHAR * schema, int schemaLength, SQLCHAR * table, int tableLength) { clearErrors(); @@ -339,8 +339,8 @@ SQLRETURN OdbcStatement::sqlTablePrivileges(SQLCHAR * catalog, int catLength, return sqlSuccess(); } -SQLRETURN OdbcStatement::sqlColumnPrivileges(SQLCHAR * catalog, int catLength, - SQLCHAR * schema, int schemaLength, +SQLRETURN OdbcStatement::sqlColumnPrivileges(SQLCHAR * catalog, int catLength, + SQLCHAR * schema, int schemaLength, SQLCHAR * table, int tableLength, SQLCHAR * column, int columnLength) { @@ -396,7 +396,7 @@ SQLRETURN OdbcStatement::sqlPrepare(SQLCHAR * sql, int sqlLength) { int lenstrSQL = (int)strlen(string); int lennewstrSQL = lenstrSQL + 4096; - + retNativeSQL = connection->connection->getNativeSql( string, lenstrSQL, tempNative. getBuffer( lennewstrSQL ), lennewstrSQL, &lenstrSQL ); if ( retNativeSQL > 0 ) @@ -421,7 +421,7 @@ SQLRETURN OdbcStatement::sqlPrepare(SQLCHAR * sql, int sqlLength) if ( !retNativeSQL ) { statement->prepareStatement (string); - + if ( statement->isActiveSelect() ) execute = &OdbcStatement::executeStatement; else if ( statement->isActiveProcedure() ) @@ -441,11 +441,11 @@ SQLRETURN OdbcStatement::sqlPrepare(SQLCHAR * sql, int sqlLength) numberColumns = statement->getStatementMetaDataIRD()->getColumnCount(); implementationParamDescriptor->updateDefinedIn(); applicationParamDescriptor->clearPrepared(); - + if ( enableAutoIPD == SQL_TRUE ) rebindParam(); } - else + else { switch ( retNativeSQL ) { @@ -509,7 +509,7 @@ void OdbcStatement::releaseResultSet() implementationRowDescriptor->clearDefined(); implementationParamDescriptor->clearDefined(); } - + lastRowsetSize = 0; countFetched = 0; isResultSetFromSystemCatalog = false; @@ -663,7 +663,7 @@ SQLRETURN OdbcStatement::sqlBindCol(int column, int targetType, SQLPOINTER targe case SQL_C_INTERVAL_MINUTE_TO_SECOND: case SQL_C_GUID: break; - + default: { JString msg; @@ -760,7 +760,7 @@ SQLRETURN OdbcStatement::fetchData() if ( fetchRetData == SQL_RD_ON ) returnData(); - + bindOffsetPtrTmp += rowBindType; ++nRow; @@ -782,11 +782,11 @@ SQLRETURN OdbcStatement::fetchData() if ( fetchRetData == SQL_RD_ON ) returnDataFromExtendedFetch(); - + bindOffsetPtrInd += sizeof(SQLLEN); ++bindOffsetPtrTmp; ++nRow; - + if ( maxRows && nRow == maxRows ) break; } @@ -885,9 +885,9 @@ SQLRETURN OdbcStatement::sqlFetchScrollCursorStatic(int orientation, int offset) rowNumber = resultSet->getPosRowInSet(); - switch(orientation) + switch(orientation) { - case SQL_FETCH_RELATIVE: + case SQL_FETCH_RELATIVE: if ( resultSet->isCurrRowsetStart() ) { if ( !rowNumber && offset < 0 ) @@ -1030,7 +1030,7 @@ SQLRETURN OdbcStatement::sqlFetchScrollCursorStatic(int orientation, int offset) return SQL_NO_DATA; } break; - + case SQL_FETCH_BOOKMARK: if ( !fetchBookmarkPtr && enFetch == FetchScroll && connection->env->useAppOdbcVersion == SQL_OV_ODBC3 ) return sqlReturn( SQL_ERROR, "HY111", "Invalid bookmark value" ); @@ -1121,14 +1121,14 @@ SQLRETURN OdbcStatement::sqlFetchScrollCursorStatic(int orientation, int offset) bindOffsetPtrInd += sizeof(SQLLEN); ++bindOffsetPtrTmp; ++nRow; - + if ( maxRows && nRow == maxRows ) break; } if ( statusPtr ) memset(statusPtr, SQL_ROW_SUCCESS, sizeof(*statusPtr) * nRow); } - + *rowCountPt = nRow; bindOffsetPtr = bindOffsetPtrSave; @@ -1158,7 +1158,7 @@ SQLRETURN OdbcStatement::sqlFetchScrollCursorStatic(int orientation, int offset) rowNumber = 0; resultSet->beforeFirst(); } - else + else { if( sqlDiagCursorRowCount ) { @@ -1186,7 +1186,7 @@ SQLRETURN OdbcStatement::sqlFetchScroll(int orientation, int offset) char strTmp[128]; sprintf(strTmp,"\t%s : bookmark %i : offset %i\n",strDebOrientFetch[orientation], fetchBookmarkPtr ? *(int*)fetchBookmarkPtr : 0, offset); - OutputDebugString(strTmp); + OutputDebugString(strTmp); #endif clearErrors(); @@ -1265,7 +1265,7 @@ SQLRETURN OdbcStatement::sqlSetPos (SQLUSMALLINT row, SQLUSMALLINT operation, SQ char strTmp[128]; sprintf(strTmp,"\t%s : current bookmark %i : row %i\n",strDebOrientSetPos[operation], fetchBookmarkPtr ? *(int*)fetchBookmarkPtr : 0, row ); - OutputDebugString(strTmp); + OutputDebugString(strTmp); #endif switch ( operation ) @@ -1313,7 +1313,7 @@ SQLRETURN OdbcStatement::sqlBulkOperations( int operation ) int columnCount = ird->metaDataOut->getColumnCount(); connection->allocHandle( SQL_HANDLE_STMT, (SQLHANDLE*)&bulkInsert ); - + *bulkInsert->applicationParamDescriptor = *applicationRowDescriptor; *bulkInsert->implementationParamDescriptor = *implementationRowDescriptor; @@ -1359,7 +1359,7 @@ SQLRETURN OdbcStatement::sqlBulkOperations( int operation ) "READ WRITE\n" "ISOLATION LEVEL\n" "READ COMMITTED NO RECORD_VERSION NO WAIT\n"; - + ret = bulkInsert->sqlExecDirect( (SQLCHAR*)(const char*)sqlTransactionString, sqlTransactionString.length() ); if ( !SQL_SUCCEEDED( ret ) ) @@ -1558,7 +1558,7 @@ SQLRETURN OdbcStatement::sqlFreeStmt(int option) case SQL_RESET_PARAMS: releaseParameters(); break; - + case SQL_DROP: statement->release(); break; @@ -1607,9 +1607,9 @@ void OdbcStatement::releaseParameters() applicationParamDescriptor->removeRecords(); } -SQLRETURN OdbcStatement::sqlStatistics(SQLCHAR * catalog, int catLength, - SQLCHAR * schema, int schemaLength, - SQLCHAR * table, int tableLength, +SQLRETURN OdbcStatement::sqlStatistics(SQLCHAR * catalog, int catLength, + SQLCHAR * schema, int schemaLength, + SQLCHAR * table, int tableLength, int unique, int reservedSic) { clearErrors(); @@ -1623,8 +1623,8 @@ SQLRETURN OdbcStatement::sqlStatistics(SQLCHAR * catalog, int catLength, try { DatabaseMetaData *metaData = connection->getMetaData(); - setResultSet (metaData->getIndexInfo (cat, scheme, tbl, - unique == SQL_INDEX_UNIQUE, + setResultSet (metaData->getIndexInfo (cat, scheme, tbl, + unique == SQL_INDEX_UNIQUE, reservedSic == SQL_QUICK)); } catch ( std::exception &ex ) @@ -1662,11 +1662,11 @@ SQLRETURN OdbcStatement::sqlPrimaryKeys(SQLCHAR * catalog, int catLength, SQLCHA return sqlSuccess(); } -SQLRETURN OdbcStatement::sqlForeignKeys (SQLCHAR * pkCatalog, int pkCatLength, - SQLCHAR * pkSchema, int pkSchemaLength, - SQLCHAR * pkTable, int pkTableLength, - SQLCHAR * fkCatalog, int fkCatalogLength, - SQLCHAR * fkSchema, int fkSchemaLength, +SQLRETURN OdbcStatement::sqlForeignKeys (SQLCHAR * pkCatalog, int pkCatLength, + SQLCHAR * pkSchema, int pkSchemaLength, + SQLCHAR * pkTable, int pkTableLength, + SQLCHAR * fkCatalog, int fkCatalogLength, + SQLCHAR * fkSchema, int fkSchemaLength, SQLCHAR * fkTable, int fkTableLength) { clearErrors(); @@ -1708,7 +1708,7 @@ SQLRETURN OdbcStatement::sqlNumResultCols(SWORD * columns) SQLRETURN OdbcStatement::sqlNumParams(SWORD * params) { clearErrors(); - + if ( statement->isActive() ) try { @@ -1727,11 +1727,11 @@ SQLRETURN OdbcStatement::sqlNumParams(SWORD * params) return sqlSuccess(); } -SQLRETURN OdbcStatement::sqlDescribeCol(int col, - SQLCHAR * colName, int nameSize, SWORD * nameLength, - SWORD * sqlType, - SQLULEN * precision, - SWORD * scale, +SQLRETURN OdbcStatement::sqlDescribeCol(int col, + SQLCHAR * colName, int nameSize, SWORD * nameLength, + SWORD * sqlType, + SQLULEN * precision, + SWORD * scale, SWORD * nullable) { clearErrors(); @@ -1756,7 +1756,7 @@ SQLRETURN OdbcStatement::sqlDescribeCol(int col, *nullable = (metaData->isNullable (col)) ? SQL_NULLABLE : SQL_NO_NULLS; #ifdef DEBUG char tempDebugStr [128]; - sprintf (tempDebugStr, "Column %.2d %31s has type %.3d, scale %.3d, precision %.3d \n", + sprintf (tempDebugStr, "Column %.2d %31s has type %.3d, scale %.3d, precision %.3d \n", col, metaData->getColumnLabel(col), metaData->getColumnType (col, realSqlType), @@ -1791,7 +1791,7 @@ SQLRETURN OdbcStatement::prepareGetData(int column, DescRecord *recordARD) recordARD->initZeroColumn(); } } - + DescRecord *recordIRD = implementationRowDescriptor->getDescRecord(column); if( !column ) @@ -1845,7 +1845,7 @@ SQLRETURN OdbcStatement::sqlGetData(int column, int cType, PTR pointer, SQLLEN b } DescRecord *record = implementationGetDataDescriptor->getDescRecord (column); - + if ( record->callType != cType ) { record->parameterType = SQL_PARAM_OUTPUT; @@ -1874,7 +1874,7 @@ SQLRETURN OdbcStatement::sqlGetData(int column, int cType, PTR pointer, SQLLEN b } else if ( !record->isPrepared && prepareGetData(column, record) ) return SQL_ERROR; - + record->dataPtr = pointer; record->length = bufferLength; record->indicatorPtr = indicatorPointer; @@ -1954,7 +1954,7 @@ SQLRETURN OdbcStatement::sqlExecDirect(SQLCHAR * sql, int sqlLength) if (retcode && retcode != SQL_SUCCESS_WITH_INFO) return retcode; - return sqlSuccess(); + return sqlSuccess(); } void OdbcStatement::rebindParam ( bool initAttrDataAtExec ) @@ -1976,8 +1976,8 @@ void OdbcStatement::rebindParam ( bool initAttrDataAtExec ) length = recordApp->indicatorPtr; else length = (SQLLEN*)((char*)recordApp->indicatorPtr + *applicationParamDescriptor->headBindOffsetPtr); - - recordApp->data_at_exec = length && + + recordApp->data_at_exec = length && (*length == SQL_DATA_AT_EXEC || *length <= SQL_LEN_DATA_AT_EXEC_OFFSET); } } @@ -2048,12 +2048,12 @@ SQLRETURN OdbcStatement::sqlDescribeParam(int parameter, SWORD * sqlType, SQLULE } SQLRETURN OdbcStatement::sqlSetParam (int parameter, int cType, int sqlType, int precision, int scale, PTR ptr, SQLLEN * length) -{ +{ return sqlBindParameter (parameter, SQL_PARAM_INPUT_OUTPUT, cType, sqlType, precision, scale, ptr, SQL_SETPARAM_VALUE_MAX, length); } -SQLRETURN OdbcStatement::sqlBindParameter(int parameter, int type, int cType, - int sqlType, int precision, int scale, +SQLRETURN OdbcStatement::sqlBindParameter(int parameter, int type, int cType, + int sqlType, int precision, int scale, PTR ptr, int bufferLength, SQLLEN * length) { clearErrors(); @@ -2476,7 +2476,7 @@ SQLRETURN OdbcStatement::sqlGetStmtAttr(int attribute, SQLPOINTER ptr, int buffe value = maxRows; TRACE02(SQL_ATTR_MAX_ROWS,value); break; - + case SQL_ATTR_MAX_LENGTH: value = maxLength; TRACE02(SQL_ATTR_MAX_LENGTH,value); @@ -2527,7 +2527,7 @@ SQLRETURN OdbcStatement::sqlGetStmtAttr(int attribute, SQLPOINTER ptr, int buffe TRACE02(SQL_ATTR_CURSOR_SENSITIVITY,value); break; - case SQL_ATTR_ENABLE_AUTO_IPD: // 15 + case SQL_ATTR_ENABLE_AUTO_IPD: // 15 value = enableAutoIPD; TRACE02(SQL_ATTR_ENABLE_AUTO_IPD,value); break; @@ -2622,7 +2622,7 @@ void OdbcStatement::bindInputOutputParam(int param, DescRecord * recordApp) { if ( !record->isDefined ) ipd->defFromMetaDataIn( param, record ); - + if( recordApp->conciseType == SQL_C_DEFAULT ) { record->setDefault ( recordApp ); @@ -2660,7 +2660,7 @@ void OdbcStatement::bindOutputColumn(int column, DescRecord * recordApp) { if ( !implementationRowDescriptor->metaDataOut ) return; - + OdbcDesc * ird = implementationRowDescriptor; DescRecord *record = ird->getDescRecord ( column ); @@ -2674,7 +2674,7 @@ void OdbcStatement::bindOutputColumn(int column, DescRecord * recordApp) { if ( !record->isDefined ) ird->defFromMetaDataOut ( column, record ); - + if( recordApp->conciseType == SQL_C_DEFAULT ) { record->setDefault ( recordApp ); @@ -2692,10 +2692,10 @@ void OdbcStatement::bindOutputColumn(int column, DescRecord * recordApp) if ( recordApp->sizeColumnExtendedFetch ) break; - // NS: if buffer is the NULL pointer, that is, if BindCol was used to + // NS: if buffer is the NULL pointer, that is, if BindCol was used to // unbind the buffer, do not care about passed zero buffer length. This // is the violation of SQL/CLI spec, but seems harmless and is necessary - // to support Firebird as the back-end for MS Project 2003 + // to support Firebird as the back-end for MS Project 2003 if ( !recordApp->dataPtr ) break; @@ -2779,14 +2779,14 @@ SQLRETURN OdbcStatement::inputParam( bool arrayColumnWiseBinding ) bindOffsetColumnWiseBinding = ( *applicationParamDescriptor->headBindOffsetPtr + rowNumberParamArray ) * record->sizeColumnExtendedFetch; - convert->setBindOffsetPtrFrom ( &bindOffsetColumnWiseBinding, + convert->setBindOffsetPtrFrom ( &bindOffsetColumnWiseBinding, &bindOffsetIndColumnWiseBinding ); } if ( record->data_at_exec ) { parameterNeedData = n; - + if ( record->startedTransfer ) { if ( record->isBlobOrArray ) @@ -2815,7 +2815,7 @@ SQLRETURN OdbcStatement::inputParam( bool arrayColumnWiseBinding ) return SQL_NEED_DATA; } - else if( record->dataPtr || + else if( record->dataPtr || (record->indicatorPtr && *record->indicatorPtr == SQL_NULL_DATA) ) { CBindColumn &bindCol = (*listBindIn)[n-1]; @@ -2850,7 +2850,7 @@ SQLRETURN OdbcStatement::executeStatement() if ( statement->isActiveSelect() && isStaticCursor() ) { - resultSet->readStaticCursor(); + resultSet->readStaticCursor(); setCursorRowCount(resultSet->getCountRowsStaticCursor()); } else if ( statement->isActiveModify() && statement->getUpdateCount() <= 0 ) @@ -2990,7 +2990,7 @@ SQLRETURN OdbcStatement::executeCommit() } return connection->sqlEndTran( SQL_COMMIT ); } - + SQLRETURN OdbcStatement::executeRollback() { if ( bulkInsert ) @@ -3045,7 +3045,7 @@ SQLRETURN OdbcStatement::sqlGetTypeInfo(int dataType) } SQLRETURN OdbcStatement::sqlParamData(SQLPOINTER *ptr) -{ +{ SQLRETURN retcode = sqlSuccess(); clearErrors(); @@ -3096,13 +3096,13 @@ SQLRETURN OdbcStatement::sqlParamData(SQLPOINTER *ptr) return SQL_NEED_DATA; } } - + try { int saveParameter = parameterNeedData; retcode = (this->*execute)(); - + if ( retcode == SQL_NEED_DATA && saveParameter != parameterNeedData ) { binding = applicationParamDescriptor->getDescRecord ( parameterNeedData ); @@ -3139,35 +3139,14 @@ SQLRETURN OdbcStatement::sqlPutData (SQLPOINTER value, SQLLEN valueSize) if ( valueSize == SQL_NTS ) if ( binding->conciseType == SQL_C_WCHAR ) - valueSize = (SQLINTEGER)wcslen( (wchar_t*)value ) * sizeof(wchar_t); + valueSize = (SQLINTEGER)SQLWCHAR_len((SQLWCHAR*)value ) * sizeof(SQLWCHAR); else // if ( binding->conciseType == SQL_C_CHAR ) valueSize = (SQLINTEGER)strlen( (char*)value ); if( valueSize ) { - if ( binding->conciseType == SQL_C_WCHAR ) - { - CBindColumn &bindParam = (*listBindIn)[ parameterNeedData - 1 ]; - - // for WcsToMbs we need to assure a L'\0' terminated source buffer - wchar_t* wcEnd = ((wchar_t*) value) + valueSize / sizeof(wchar_t); - wchar_t wcSave = *wcEnd; - *wcEnd = L'\0'; - - // ipd->headSqlVarPtr->getSqlMultiple() cannot be used to calculate the conversion - // buffer size, because for blobs it seems to return always 1 - // so we call the conversion function to calculate the required buffer size - // size_t lenMbs = valueSize / sizeof(wchar_t) * ipd->headSqlVarPtr->getSqlMultiple(); - size_t lenMbs = bindParam.impRecord->WcsToMbs(NULL, (const wchar_t*)value, 0 ); - char* tempValue = new char[lenMbs+1]; - lenMbs = bindParam.impRecord->WcsToMbs(tempValue, (const wchar_t*)value, lenMbs ); - binding->putBlobSegmentData (lenMbs, tempValue); - delete [] tempValue; - - *wcEnd = wcSave; - } - else - binding->putBlobSegmentData (valueSize, value); + // Put data as is, recode later, on real store + binding->putBlobSegmentData (valueSize, value); } } else @@ -3177,7 +3156,7 @@ SQLRETURN OdbcStatement::sqlPutData (SQLPOINTER value, SQLLEN valueSize) if ( valueSize == SQL_NTS ) if ( binding->conciseType == SQL_C_WCHAR ) - valueSize = (SQLINTEGER)wcslen( (wchar_t*)value ) * sizeof(wchar_t); + valueSize = (SQLINTEGER)SQLWCHAR_len(reinterpret_cast(value)) * sizeof(SQLWCHAR); else // if ( binding->conciseType == SQL_C_CHAR ) valueSize = (SQLINTEGER)strlen( (char*)value ); @@ -3309,7 +3288,7 @@ SQLRETURN OdbcStatement::sqlSetStmtAttr(int attribute, SQLPOINTER ptr, int lengt applicationRowDescriptor->headArraySize = (intptr_t) ptr; TRACE02(SQL_ROWSET_SIZE,(intptr_t) ptr); break; - + case SQL_ATTR_ROWS_FETCHED_PTR: // 26 implementationRowDescriptor->headRowsProcessedPtr = (SQLULEN*) ptr; TRACE02(SQL_ATTR_ROWS_FETCHED_PTR,(intptr_t) ptr); @@ -3385,7 +3364,7 @@ SQLRETURN OdbcStatement::sqlSetStmtAttr(int attribute, SQLPOINTER ptr, int lengt maxRows = (intptr_t) ptr; TRACE02(SQL_ATTR_MAX_ROWS,(intptr_t) ptr); break; - + case SQL_ATTR_MAX_LENGTH: if ( length == SQL_IS_POINTER ) maxLength = *(intptr_t*) ptr; @@ -3436,7 +3415,7 @@ SQLRETURN OdbcStatement::sqlSetStmtAttr(int attribute, SQLPOINTER ptr, int lengt TRACE02(SQL_ATTR_ROW_OPERATION_PTR,(intptr_t) ptr); break; - case SQL_ATTR_ENABLE_AUTO_IPD: // 15 + case SQL_ATTR_ENABLE_AUTO_IPD: // 15 enableAutoIPD = (intptr_t) ptr; TRACE02(SQL_ATTR_ENABLE_AUTO_IPD,(intptr_t) ptr); break; @@ -3507,7 +3486,7 @@ SQLRETURN OdbcStatement::sqlRowCount(SQLLEN *rowCount) *rowCount = rowNumber; else if ( statement->isActive() ) *rowCount = statement->getUpdateCount(); - else + else *rowCount = -1; } } @@ -3615,8 +3594,8 @@ SQLRETURN OdbcStatement::sqlColAttribute( int column, int fieldId, SQLPOINTER at case SQL_DESC_TYPE_NAME: case SQL_DESC_LOCAL_TYPE_NAME: - string = metaData->getColumnTypeName (column); - break; + string = metaData->getColumnTypeName (column); + break; case SQL_DESC_BASE_TABLE_NAME: case SQL_DESC_TABLE_NAME: @@ -3636,7 +3615,7 @@ SQLRETURN OdbcStatement::sqlColAttribute( int column, int fieldId, SQLPOINTER at break; case MSSQL_CA_SS_COLUMN_HIDDEN: // TRUE if the column referenced is part of a hidden primary key (FOR BROWSE) - value = 0; + value = 0; break; case MSSQL_CA_SS_COLUMN_KEY: // TRUE if the column referenced is part of a primary key for the row (FOR BROWSE)