1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_connectivity.hxx"
26 #include "odbc/OTools.hxx"
27 #include "odbc/OConnection.hxx"
28 #include "odbc/ODatabaseMetaData.hxx"
29 #include "odbc/OFunctions.hxx"
30 #include "odbc/ODriver.hxx"
31 #include "odbc/OStatement.hxx"
32 #include "odbc/OPreparedStatement.hxx"
33 #include <com/sun/star/sdbc/ColumnValue.hpp>
34 #include <com/sun/star/sdbc/XRow.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <connectivity/dbcharset.hxx>
37 #include <connectivity/FValue.hxx>
38 #include <comphelper/extract.hxx>
39 #include "diagnose_ex.h"
40 #include <connectivity/dbexception.hxx>
41 
42 #include <string.h>
43 
44 using namespace connectivity::odbc;
45 using namespace connectivity;
46 using namespace dbtools;
47 
48 //------------------------------------------------------------------------------
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::beans;
52 using namespace com::sun::star::sdbc;
53 // --------------------------------------------------------------------------------
OConnection(const SQLHANDLE _pDriverHandle,ODBCDriver * _pDriver)54 OConnection::OConnection(const SQLHANDLE _pDriverHandle,ODBCDriver*	_pDriver)
55 						 : OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this)
56                          ,m_pDriver(_pDriver)
57 						 ,m_pDriverHandleCopy(_pDriverHandle)
58                          ,m_nStatementCount(0)
59 						 ,m_bClosed(sal_True)
60                          ,m_bUseCatalog(sal_False)
61                          ,m_bUseOldDateFormat(sal_False)
62 						 ,m_bParameterSubstitution(sal_False)
63 						 ,m_bIgnoreDriverPrivileges(sal_False)
64                          ,m_bPreventGetVersionColumns(sal_False)
65                          ,m_bReadOnly(sal_True)
66 {
67 	m_pDriver->acquire();
68 }
69 //-----------------------------------------------------------------------------
~OConnection()70 OConnection::~OConnection()
71 {
72 	if(!isClosed(  ))
73 		close();
74 
75 	if ( SQL_NULL_HANDLE != m_aConnectionHandle )
76 		N3SQLFreeHandle( SQL_HANDLE_DBC, m_aConnectionHandle );
77 	m_aConnectionHandle = SQL_NULL_HANDLE;
78 
79 	m_pDriver->release();
80 	m_pDriver = NULL;
81 }
82 //-----------------------------------------------------------------------------
release()83 void SAL_CALL OConnection::release() throw()
84 {
85 	relase_ChildImpl();
86 }
87 // -----------------------------------------------------------------------------
getOdbcFunction(sal_Int32 _nIndex) const88 oslGenericFunction OConnection::getOdbcFunction(sal_Int32 _nIndex)  const
89 {
90 	OSL_ENSURE(m_pDriver,"OConnection::getOdbcFunction: m_pDriver is null!");
91 	return m_pDriver->getOdbcFunction(_nIndex);
92 }
93 //-----------------------------------------------------------------------------
OpenConnection(const::rtl::OUString & aConnectStr,sal_Int32 nTimeOut,sal_Bool bSilent)94 SQLRETURN OConnection::OpenConnection(const ::rtl::OUString& aConnectStr,sal_Int32 nTimeOut, sal_Bool bSilent)
95 {
96 	::osl::MutexGuard aGuard( m_aMutex );
97 
98 	if (m_aConnectionHandle == SQL_NULL_HANDLE)
99 		return -1;
100 
101 	SQLRETURN nSQLRETURN = 0;
102 	SDB_ODBC_CHAR szConnStrOut[4096];
103 	SDB_ODBC_CHAR szConnStrIn[2048];
104 	SQLSMALLINT cbConnStrOut;
105 	memset(szConnStrOut,'\0',4096);
106 	memset(szConnStrIn,'\0',2048);
107 	::rtl::OString aConStr(::rtl::OUStringToOString(aConnectStr,getTextEncoding()));
108 	memcpy(szConnStrIn, (SDB_ODBC_CHAR*) aConStr.getStr(), ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()));
109 
110 #ifndef MACOSX
111 	N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_LOGIN_TIMEOUT,(SQLPOINTER)nTimeOut,SQL_IS_UINTEGER);
112 	// Verbindung aufbauen
113 #endif
114 
115 #ifdef LINUX
116     OSL_UNUSED( bSilent );
117 	nSQLRETURN = N3SQLDriverConnect(m_aConnectionHandle,
118 					  NULL,
119 					  szConnStrIn,
120 					  (SQLSMALLINT) ::std::min((sal_Int32)2048,aConStr.getLength()),
121 					  szConnStrOut,
122 					  (SQLSMALLINT) (sizeof(szConnStrOut)/sizeof(SDB_ODBC_CHAR)) -1,
123 					  &cbConnStrOut,
124 					  SQL_DRIVER_NOPROMPT);
125 	if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA || SQL_SUCCESS_WITH_INFO == nSQLRETURN)
126 		return nSQLRETURN;
127 #else
128 
129 	SQLUSMALLINT nSilent =  bSilent ? SQL_DRIVER_NOPROMPT : SQL_DRIVER_COMPLETE;
130 	nSQLRETURN = N3SQLDriverConnect(m_aConnectionHandle,
131 					  NULL,
132 					  szConnStrIn,
133 					  (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()),
134 					  szConnStrOut,
135 					  (SQLSMALLINT) sizeof szConnStrOut,
136 					  &cbConnStrOut,
137 					  nSilent);
138 	if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA)
139 		return nSQLRETURN;
140 
141 	m_bClosed = sal_False;
142 
143 #endif //LINUX
144 
145 	try
146 	{
147 		::rtl::OUString aVal;
148 		OTools::GetInfo(this,m_aConnectionHandle,SQL_DATA_SOURCE_READ_ONLY,aVal,*this,getTextEncoding());
149 		m_bReadOnly = !aVal.compareToAscii("Y");
150 	}
151 	catch(Exception&)
152 	{
153 		m_bReadOnly = sal_True;
154 	}
155 	try
156 	{
157 		::rtl::OUString sVersion;
158 		OTools::GetInfo(this,m_aConnectionHandle,SQL_DRIVER_ODBC_VER,sVersion,*this,getTextEncoding());
159 		m_bUseOldDateFormat	=  sVersion == ::rtl::OUString::createFromAscii("02.50") || sVersion == ::rtl::OUString::createFromAscii("02.00");
160 	}
161 	catch(Exception&)
162 	{
163 	}
164 
165 
166 	// autocoomit ist immer default
167 
168 	if (!m_bReadOnly)
169 		N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON,SQL_IS_INTEGER);
170 
171 	return nSQLRETURN;
172 }
173 //-----------------------------------------------------------------------------
Construct(const::rtl::OUString & url,const Sequence<PropertyValue> & info)174 SQLRETURN OConnection::Construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info)  throw(SQLException)
175 {
176 	m_aConnectionHandle  = SQL_NULL_HANDLE;
177 	m_sURL	= url;
178 	setConnectionInfo(info);
179 
180 	// Connection allozieren
181 	N3SQLAllocHandle(SQL_HANDLE_DBC,m_pDriverHandleCopy,&m_aConnectionHandle);
182 	if(m_aConnectionHandle == SQL_NULL_HANDLE)
183 		throw SQLException();
184 
185 	sal_Int32 nLen = url.indexOf(':');
186 	nLen = url.indexOf(':',nLen+1);
187 	::rtl::OUString aDSN(RTL_CONSTASCII_USTRINGPARAM("DSN=")), aUID, aPWD, aSysDrvSettings;
188 	aDSN += url.copy(nLen+1);
189 
190 	const char* pUser		= "user";
191 	const char* pTimeout	= "Timeout";
192 	const char* pSilent		= "Silent";
193 	const char* pPwd		= "password";
194 	const char* pUseCatalog = "UseCatalog";
195 	const char* pSysDrv		= "SystemDriverSettings";
196 	const char* pCharSet	= "CharSet";
197 	const char* pParaName	= "ParameterNameSubstitution";
198 	const char* pPrivName	= "IgnoreDriverPrivileges";
199     const char* pVerColName = "PreventGetVersionColumns";   // #i60273#
200 	const char* pRetrieving	= "IsAutoRetrievingEnabled";
201 	const char* pRetriStmt	= "AutoRetrievingStatement";
202 
203 	sal_Int32 nTimeout = 20;
204 	sal_Bool bSilent = sal_True;
205 	const PropertyValue *pBegin	= info.getConstArray();
206 	const PropertyValue *pEnd	= pBegin + info.getLength();
207 	for(;pBegin != pEnd;++pBegin)
208 	{
209 		if(!pBegin->Name.compareToAscii(pTimeout))
210 			OSL_VERIFY( pBegin->Value >>= nTimeout );
211 		else if(!pBegin->Name.compareToAscii(pSilent))
212 			OSL_VERIFY( pBegin->Value >>= bSilent );
213 		else if(!pBegin->Name.compareToAscii(pPrivName))
214 			OSL_VERIFY( pBegin->Value >>= m_bIgnoreDriverPrivileges );
215         else if(!pBegin->Name.compareToAscii(pVerColName))
216             OSL_VERIFY( pBegin->Value >>= m_bPreventGetVersionColumns );
217 		else if(!pBegin->Name.compareToAscii(pParaName))
218 			OSL_VERIFY( pBegin->Value >>= m_bParameterSubstitution );
219 		else if(!pBegin->Name.compareToAscii(pRetrieving))
220 		{
221 			sal_Bool bAutoRetrievingEnabled = sal_False;
222 			OSL_VERIFY( pBegin->Value >>= bAutoRetrievingEnabled );
223 			enableAutoRetrievingEnabled(bAutoRetrievingEnabled);
224 		}
225 		else if(!pBegin->Name.compareToAscii(pRetriStmt))
226 		{
227 			::rtl::OUString sGeneratedValueStatement;
228 			OSL_VERIFY( pBegin->Value >>= sGeneratedValueStatement );
229 			setAutoRetrievingStatement(sGeneratedValueStatement);
230 		}
231 		else if(!pBegin->Name.compareToAscii(pUser))
232 		{
233 			OSL_VERIFY( pBegin->Value >>= aUID );
234 			aDSN = aDSN + ::rtl::OUString::createFromAscii(";UID=") + aUID;
235 		}
236 		else if(!pBegin->Name.compareToAscii(pPwd))
237 		{
238 			OSL_VERIFY( pBegin->Value >>= aPWD );
239 			aDSN = aDSN + ::rtl::OUString::createFromAscii(";PWD=") + aPWD;
240 		}
241 		else if(!pBegin->Name.compareToAscii(pUseCatalog))
242 		{
243 			 OSL_VERIFY( pBegin->Value >>= m_bUseCatalog );
244 		}
245 		else if(!pBegin->Name.compareToAscii(pSysDrv))
246 		{
247 			OSL_VERIFY( pBegin->Value >>= aSysDrvSettings );
248 			aDSN += ::rtl::OUString::createFromAscii(";");
249 			aDSN += aSysDrvSettings;
250 		}
251 		else if(0 == pBegin->Name.compareToAscii(pCharSet))
252 		{
253 			::rtl::OUString sIanaName;
254 			OSL_VERIFY( pBegin->Value >>= sIanaName );
255 
256 			::dbtools::OCharsetMap aLookupIanaName;
257 			::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA());
258 			if (aLookup != aLookupIanaName.end())
259 				m_nTextEncoding = (*aLookup).getEncoding();
260 			else
261 				m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW;
262 			if(m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW)
263 				m_nTextEncoding = osl_getThreadTextEncoding();
264 		}
265 	}
266 	m_sUser = aUID;
267 
268 	SQLRETURN nSQLRETURN = OpenConnection(aDSN,nTimeout, bSilent);
269 	if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA)
270 	{
271 		OTools::ThrowException(this,nSQLRETURN,m_aConnectionHandle,SQL_HANDLE_DBC,*this,sal_False);
272 	}
273 	return nSQLRETURN;
274 }
275 // XServiceInfo
276 // --------------------------------------------------------------------------------
277 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.odbc.OConnection", "com.sun.star.sdbc.Connection")
278 
279 // --------------------------------------------------------------------------------
createStatement()280 Reference< XStatement > SAL_CALL OConnection::createStatement(  ) throw(SQLException, RuntimeException)
281 {
282 	::osl::MutexGuard aGuard( m_aMutex );
283 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
284 
285 	Reference< XStatement > xReturn = new OStatement(this);
286 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
287 	return xReturn;
288 }
289 // --------------------------------------------------------------------------------
prepareStatement(const::rtl::OUString & sql)290 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
291 {
292 	::osl::MutexGuard aGuard( m_aMutex );
293 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
294 
295 	Reference< XPreparedStatement > xReturn = new OPreparedStatement(this,sql);
296 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
297 	return xReturn;
298 }
299 // --------------------------------------------------------------------------------
prepareCall(const::rtl::OUString &)300 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const ::rtl::OUString& /*sql*/ ) throw(SQLException, RuntimeException)
301 {
302     ::dbtools::throwFeatureNotImplementedException( "XConnection::prepareCall", *this );
303     return NULL;
304 }
305 // --------------------------------------------------------------------------------
nativeSQL(const::rtl::OUString & sql)306 ::rtl::OUString SAL_CALL OConnection::nativeSQL( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
307 {
308 	::osl::MutexGuard aGuard( m_aMutex );
309 
310 	::rtl::OString aSql(::rtl::OUStringToOString(sql.getStr(),getTextEncoding()));
311 	char pOut[2048];
312 	SQLINTEGER nOutLen;
313 	OTools::ThrowException(this,N3SQLNativeSql(m_aConnectionHandle,(SDB_ODBC_CHAR*)aSql.getStr(),aSql.getLength(),(SDB_ODBC_CHAR*)pOut,sizeof pOut - 1,&nOutLen),m_aConnectionHandle,SQL_HANDLE_DBC,*this);
314 	return ::rtl::OUString(pOut,nOutLen,getTextEncoding());
315 }
316 // --------------------------------------------------------------------------------
setAutoCommit(sal_Bool autoCommit)317 void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) throw(SQLException, RuntimeException)
318 {
319 	::osl::MutexGuard aGuard( m_aMutex );
320 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
321 
322 
323 	OTools::ThrowException(this,N3SQLSetConnectAttr(m_aConnectionHandle,
324 								   SQL_ATTR_AUTOCOMMIT,
325 								   (SQLPOINTER)((autoCommit) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF) ,SQL_IS_INTEGER),
326 								   m_aConnectionHandle,SQL_HANDLE_DBC,*this);
327 }
328 // --------------------------------------------------------------------------------
getAutoCommit()329 sal_Bool SAL_CALL OConnection::getAutoCommit(  ) throw(SQLException, RuntimeException)
330 {
331 	::osl::MutexGuard aGuard( m_aMutex );
332 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
333 
334 
335 	sal_uInt32 nOption = 0;
336 	OTools::ThrowException(this,N3SQLGetConnectAttr(m_aConnectionHandle,
337 								   SQL_ATTR_AUTOCOMMIT, &nOption,0,0),m_aConnectionHandle,SQL_HANDLE_DBC,*this);
338 	return nOption == SQL_AUTOCOMMIT_ON ;
339 }
340 // --------------------------------------------------------------------------------
commit()341 void SAL_CALL OConnection::commit(  ) throw(SQLException, RuntimeException)
342 {
343 	::osl::MutexGuard aGuard( m_aMutex );
344 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
345 
346 
347 	OTools::ThrowException(this,N3SQLEndTran(SQL_HANDLE_DBC,m_aConnectionHandle,SQL_COMMIT),m_aConnectionHandle,SQL_HANDLE_DBC,*this);
348 }
349 // --------------------------------------------------------------------------------
rollback()350 void SAL_CALL OConnection::rollback(  ) throw(SQLException, RuntimeException)
351 {
352 	::osl::MutexGuard aGuard( m_aMutex );
353 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
354 
355 
356 	OTools::ThrowException(this,N3SQLEndTran(SQL_HANDLE_DBC,m_aConnectionHandle,SQL_ROLLBACK),m_aConnectionHandle,SQL_HANDLE_DBC,*this);
357 }
358 // --------------------------------------------------------------------------------
isClosed()359 sal_Bool SAL_CALL OConnection::isClosed(  ) throw(SQLException, RuntimeException)
360 {
361 	::osl::MutexGuard aGuard( m_aMutex );
362 
363 	return OConnection_BASE::rBHelper.bDisposed;
364 }
365 // --------------------------------------------------------------------------------
getMetaData()366 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData(  ) throw(SQLException, RuntimeException)
367 {
368 	::osl::MutexGuard aGuard( m_aMutex );
369 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
370 
371 	Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
372 	if(!xMetaData.is())
373 	{
374 		xMetaData = new ODatabaseMetaData(m_aConnectionHandle,this);
375 		m_xMetaData = xMetaData;
376 	}
377 
378 	return xMetaData;
379 }
380 // --------------------------------------------------------------------------------
setReadOnly(sal_Bool readOnly)381 void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) throw(SQLException, RuntimeException)
382 {
383 	::osl::MutexGuard aGuard( m_aMutex );
384 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
385 
386 
387 	OTools::ThrowException(this,
388         N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_ACCESS_MODE,reinterpret_cast< SQLPOINTER >( readOnly ),SQL_IS_INTEGER),
389 		m_aConnectionHandle,SQL_HANDLE_DBC,*this);
390 }
391 // --------------------------------------------------------------------------------
isReadOnly()392 sal_Bool SAL_CALL OConnection::isReadOnly() throw(SQLException, RuntimeException)
393 {
394 	// const member which will initialized only once
395 	return m_bReadOnly;
396 }
397 // --------------------------------------------------------------------------------
setCatalog(const::rtl::OUString & catalog)398 void SAL_CALL OConnection::setCatalog( const ::rtl::OUString& catalog ) throw(SQLException, RuntimeException)
399 {
400 	::osl::MutexGuard aGuard( m_aMutex );
401 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
402 
403 
404 	::rtl::OString aCat(::rtl::OUStringToOString(catalog.getStr(),getTextEncoding()));
405 	OTools::ThrowException(this,
406 		N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,(SDB_ODBC_CHAR*)aCat.getStr(),SQL_NTS),
407 		m_aConnectionHandle,SQL_HANDLE_DBC,*this);
408 }
409 // --------------------------------------------------------------------------------
getCatalog()410 ::rtl::OUString SAL_CALL OConnection::getCatalog(  ) throw(SQLException, RuntimeException)
411 {
412 	::osl::MutexGuard aGuard( m_aMutex );
413 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
414 
415 
416 	sal_Int32 nValueLen;
417 	char pCat[1024];
418 	OTools::ThrowException(this,
419 		N3SQLGetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,(SDB_ODBC_CHAR*)pCat,(sizeof pCat)-1,&nValueLen),
420 		m_aConnectionHandle,SQL_HANDLE_DBC,*this);
421 
422 	return ::rtl::OUString(pCat,nValueLen,getTextEncoding());
423 }
424 // --------------------------------------------------------------------------------
setTransactionIsolation(sal_Int32 level)425 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 level ) throw(SQLException, RuntimeException)
426 {
427 	::osl::MutexGuard aGuard( m_aMutex );
428 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
429 
430 
431 	OTools::ThrowException(this,N3SQLSetConnectAttr(m_aConnectionHandle,
432 								   SQL_ATTR_TXN_ISOLATION,
433 								   (SQLPOINTER)level,SQL_IS_INTEGER),
434 								   m_aConnectionHandle,SQL_HANDLE_DBC,*this);
435 }
436 // --------------------------------------------------------------------------------
getTransactionIsolation()437 sal_Int32 SAL_CALL OConnection::getTransactionIsolation(  ) throw(SQLException, RuntimeException)
438 {
439 	::osl::MutexGuard aGuard( m_aMutex );
440 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
441 
442 
443 	sal_Int32 nTxn = 0;
444 	SQLINTEGER nValueLen;
445 	OTools::ThrowException(this,
446 		N3SQLGetConnectAttr(m_aConnectionHandle,SQL_ATTR_TXN_ISOLATION,&nTxn,sizeof nTxn,&nValueLen),
447 		m_aConnectionHandle,SQL_HANDLE_DBC,*this);
448 	return nTxn;
449 }
450 // --------------------------------------------------------------------------------
getTypeMap()451 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getTypeMap(  ) throw(SQLException, RuntimeException)
452 {
453 	::osl::MutexGuard aGuard( m_aMutex );
454 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
455 
456 
457 	return NULL;
458 }
459 // --------------------------------------------------------------------------------
setTypeMap(const Reference<::com::sun::star::container::XNameAccess> &)460 void SAL_CALL OConnection::setTypeMap( const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException)
461 {
462     ::dbtools::throwFeatureNotImplementedException( "XConnection::setTypeMap", *this );
463 }
464 // --------------------------------------------------------------------------------
465 // XCloseable
close()466 void SAL_CALL OConnection::close(  ) throw(SQLException, RuntimeException)
467 {
468 	{
469 		::osl::MutexGuard aGuard( m_aMutex );
470 		checkDisposed(OConnection_BASE::rBHelper.bDisposed);
471 
472 	}
473 	dispose();
474 }
475 // --------------------------------------------------------------------------------
476 // XWarningsSupplier
getWarnings()477 Any SAL_CALL OConnection::getWarnings(  ) throw(SQLException, RuntimeException)
478 {
479 	return Any();
480 }
481 // --------------------------------------------------------------------------------
clearWarnings()482 void SAL_CALL OConnection::clearWarnings(  ) throw(SQLException, RuntimeException)
483 {
484 }
485 //--------------------------------------------------------------------
buildTypeInfo()486 void OConnection::buildTypeInfo() throw( SQLException)
487 {
488 	::osl::MutexGuard aGuard( m_aMutex );
489 
490 	Reference< XResultSet> xRs = getMetaData ()->getTypeInfo ();
491 	if(xRs.is())
492 	{
493 		Reference< XRow> xRow(xRs,UNO_QUERY);
494 		// Information for a single SQL type
495 
496 		::connectivity::ORowSetValue aValue;
497 		::std::vector<sal_Int32> aTypes;
498 		Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY)->getMetaData();
499         sal_Int32 nCount = xResultSetMetaData->getColumnCount();
500 		// Loop on the result set until we reach end of file
501 		while (xRs->next ())
502 		{
503 			OTypeInfo aInfo;
504 			sal_Int32 nPos = 1;
505             if ( aTypes.empty() )
506             {
507                 if ( nCount < 1 )
508                     nCount = 18;
509                 aTypes.reserve(nCount+1);
510                 aTypes.push_back(-1);
511                 for (sal_Int32 j = 1; j <= nCount ; ++j)
512                     aTypes.push_back(xResultSetMetaData->getColumnType(j));
513             }
514 
515             aValue.fill(nPos,aTypes[nPos],xRow);
516 			aInfo.aTypeName		= aValue;
517 			++nPos;
518             aValue.fill(nPos,aTypes[nPos],xRow);
519 			aInfo.nType			= aValue;
520 			++nPos;
521             aValue.fill(nPos,aTypes[nPos],xRow);
522 			aInfo.nPrecision		= aValue;
523 			++nPos;
524             aValue.fill(nPos,aTypes[nPos],xRow);
525 			aInfo.aLiteralPrefix	= aValue;
526 			++nPos;
527             aValue.fill(nPos,aTypes[nPos],xRow);
528 			aInfo.aLiteralSuffix	= aValue;
529 			++nPos;
530             aValue.fill(nPos,aTypes[nPos],xRow);
531 			aInfo.aCreateParams	= aValue;
532 			++nPos;
533             aValue.fill(nPos,aTypes[nPos],xRow);
534 			aInfo.bNullable		= (sal_Int32)aValue == ColumnValue::NULLABLE;
535 			++nPos;
536             aValue.fill(nPos,aTypes[nPos],xRow);
537 			aInfo.bCaseSensitive	= (sal_Bool)aValue;
538 			++nPos;
539             aValue.fill(nPos,aTypes[nPos],xRow);
540 			aInfo.nSearchType		= aValue;
541 			++nPos;
542             aValue.fill(nPos,aTypes[nPos],xRow);
543 			aInfo.bUnsigned		= (sal_Bool)aValue;
544 			++nPos;
545             aValue.fill(nPos,aTypes[nPos],xRow);
546 			aInfo.bCurrency		= (sal_Bool)aValue;
547 			++nPos;
548             aValue.fill(nPos,aTypes[nPos],xRow);
549 			aInfo.bAutoIncrement	= (sal_Bool)aValue;
550 			++nPos;
551             aValue.fill(nPos,aTypes[nPos],xRow);
552 			aInfo.aLocalTypeName	= aValue;
553 			++nPos;
554             aValue.fill(nPos,aTypes[nPos],xRow);
555 			aInfo.nMinimumScale	= aValue;
556 			++nPos;
557             aValue.fill(nPos,aTypes[nPos],xRow);
558 			aInfo.nMaximumScale	= aValue;
559             if ( nCount >= 18 )
560             {
561                 nPos = 18;
562                 aValue.fill(nPos,aTypes[nPos],xRow);
563 			    aInfo.nNumPrecRadix	= aValue;
564             }
565 
566 			// check if values are less than zero like it happens in a oracle jdbc driver
567 			if( aInfo.nPrecision < 0)
568 				aInfo.nPrecision = 0;
569 			if( aInfo.nMinimumScale < 0)
570 				aInfo.nMinimumScale = 0;
571 			if( aInfo.nMaximumScale < 0)
572 				aInfo.nMaximumScale = 0;
573 			if( aInfo.nNumPrecRadix < 0)
574 				aInfo.nNumPrecRadix = 10;
575 
576 			// Now that we have the type info, save it
577 			// in the Hashtable if we don't already have an
578 			// entry for this SQL type.
579 
580 			m_aTypeInfo.push_back(aInfo);
581 		}
582 
583 		// Close the result set/statement.
584 
585 		Reference< XCloseable> xClose(xRs,UNO_QUERY);
586 		if(xClose.is())
587 			xClose->close();
588 	}
589 }
590 //------------------------------------------------------------------------------
disposing()591 void OConnection::disposing()
592 {
593 	::osl::MutexGuard aGuard(m_aMutex);
594 
595     OConnection_BASE::disposing();
596 
597 	for (::std::map< SQLHANDLE,OConnection*>::iterator aConIter = m_aConnections.begin();aConIter != m_aConnections.end();++aConIter )
598 		aConIter->second->dispose();
599 
600 	::std::map< SQLHANDLE,OConnection*>().swap(m_aConnections);
601 
602 	if(!m_bClosed)
603 		N3SQLDisconnect(m_aConnectionHandle);
604 	m_bClosed	= sal_True;
605 
606 	dispose_ChildImpl();
607 }
608 // -----------------------------------------------------------------------------
cloneConnection()609 OConnection* OConnection::cloneConnection()
610 {
611 	return new OConnection(m_pDriverHandleCopy,m_pDriver);
612 }
613 // -----------------------------------------------------------------------------
createStatementHandle()614 SQLHANDLE OConnection::createStatementHandle()
615 {
616 	OConnection* pConnectionTemp = this;
617 	sal_Bool bNew = sal_False;
618 	try
619 	{
620 		sal_Int32 nMaxStatements = getMetaData()->getMaxStatements();
621 		if(nMaxStatements && nMaxStatements <= m_nStatementCount)
622 		{
623 			OConnection* pConnection = cloneConnection();
624 			pConnection->acquire();
625 			pConnection->Construct(m_sURL,getConnectionInfo());
626 			pConnectionTemp = pConnection;
627 			bNew = sal_True;
628 		}
629 	}
630 	catch(SQLException&)
631 	{
632 	}
633 
634 	SQLHANDLE aStatementHandle = SQL_NULL_HANDLE;
635 	SQLRETURN nRetcode = N3SQLAllocHandle(SQL_HANDLE_STMT,pConnectionTemp->getConnection(),&aStatementHandle);
636     OSL_UNUSED( nRetcode );
637 	++m_nStatementCount;
638 	if(bNew)
639 		m_aConnections.insert(::std::map< SQLHANDLE,OConnection*>::value_type(aStatementHandle,pConnectionTemp));
640 
641 	return aStatementHandle;
642 
643 }
644 // -----------------------------------------------------------------------------
freeStatementHandle(SQLHANDLE & _pHandle)645 void OConnection::freeStatementHandle(SQLHANDLE& _pHandle)
646 {
647 	::std::map< SQLHANDLE,OConnection*>::iterator aFind = m_aConnections.find(_pHandle);
648 
649 	N3SQLFreeStmt(_pHandle,SQL_RESET_PARAMS);
650 	N3SQLFreeStmt(_pHandle,SQL_UNBIND);
651 	N3SQLFreeStmt(_pHandle,SQL_CLOSE);
652 	N3SQLFreeHandle(SQL_HANDLE_STMT,_pHandle);
653 
654 	_pHandle = SQL_NULL_HANDLE;
655 
656 	if(aFind != m_aConnections.end())
657 	{
658 		aFind->second->dispose();
659 		m_aConnections.erase(aFind);
660 	}
661 	--m_nStatementCount;
662 }
663 // -----------------------------------------------------------------------------
664 
665 
666 
667