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 #include "SConnection.hxx"
25 
26 #include "SDatabaseMetaData.hxx"
27 #include "SDriver.hxx"
28 #include "SStatement.hxx"
29 #include "SPreparedStatement.hxx"
30 #include <com/sun/star/sdbc/ColumnValue.hpp>
31 #include <com/sun/star/sdbc/XRow.hpp>
32 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 
35 using namespace connectivity::skeleton;
36 
37 //------------------------------------------------------------------------------
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::lang;
40 using namespace com::sun::star::beans;
41 using namespace com::sun::star::sdbc;
42 // --------------------------------------------------------------------------------
OConnection(SkeletonDriver * _pDriver)43 OConnection::OConnection(SkeletonDriver*	_pDriver)
44 						 : OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this),
45 						 OMetaConnection_BASE(m_aMutex),
46 						 m_pDriver(_pDriver),
47 						 m_bClosed(sal_False),
48 						 m_xMetaData(NULL),
49 						 m_bUseCatalog(sal_False),
50 						 m_bUseOldDateFormat(sal_False)
51 {
52 	m_pDriver->acquire();
53 }
54 //-----------------------------------------------------------------------------
~OConnection()55 OConnection::~OConnection()
56 {
57 	if(!isClosed())
58 		close();
59 	m_pDriver->release();
60 	m_pDriver = NULL;
61 }
62 //-----------------------------------------------------------------------------
release()63 void SAL_CALL OConnection::release() throw()
64 {
65 	relase_ChildImpl();
66 }
67 // -----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
construct(const::rtl::OUString & url,const Sequence<PropertyValue> & info)69 void OConnection::construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info)  throw(SQLException)
70 {
71 	osl_incrementInterlockedCount( &m_refCount );
72 
73 	// some example code how to get the information out of the sequence
74 
75 	sal_Int32 nLen = url.indexOf(':');
76 	nLen = url.indexOf(':',nLen+1);
77 	::rtl::OUString aDSN(RTL_CONSTASCII_USTRINGPARAM("DSN=")), aUID, aPWD, aSysDrvSettings;
78 	aDSN += url.copy(nLen+1);
79 
80 	const char* pUser		= "user";
81 	const char* pTimeout	= "Timeout";
82 	const char* pSilent		= "Silent";
83 	const char* pPwd		= "password";
84 	const char* pUseCatalog = "UseCatalog";
85 	const char* pSysDrv		= "SystemDriverSettings";
86 
87 	sal_Int32 nTimeout = 20;
88 	sal_Bool bSilent = sal_True;
89 	const PropertyValue *pBegin	= info.getConstArray();
90 	const PropertyValue *pEnd	= pBegin + info.getLength();
91 	for(;pBegin != pEnd;++pBegin)
92 	{
93 		if(!pBegin->Name.compareToAscii(pTimeout))
94 			pBegin->Value >>= nTimeout;
95 		else if(!pBegin->Name.compareToAscii(pSilent))
96 			pBegin->Value >>= bSilent;
97 		else if(!pBegin->Name.compareToAscii(pUser))
98 		{
99 			pBegin->Value >>= aUID;
100 			aDSN = aDSN + ::rtl::OUString::createFromAscii(";UID=") + aUID;
101 		}
102 		else if(!pBegin->Name.compareToAscii(pPwd))
103 		{
104 			pBegin->Value >>= aPWD;
105 			aDSN = aDSN + ::rtl::OUString::createFromAscii(";PWD=") + aPWD;
106 		}
107 		else if(!pBegin->Name.compareToAscii(pUseCatalog))
108 		{
109 			pBegin->Value >>= m_bUseCatalog;
110 		}
111 		else if(!pBegin->Name.compareToAscii(pSysDrv))
112 		{
113 			pBegin->Value >>= aSysDrvSettings;
114 			aDSN += ::rtl::OUString::createFromAscii(";");
115 			aDSN += aSysDrvSettings;
116 		}
117 	}
118 	m_sUser = aUID;
119 
120 	osl_decrementInterlockedCount( &m_refCount );
121 }
122 // XServiceInfo
123 // --------------------------------------------------------------------------------
124 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.skeleton.OConnection", "com.sun.star.sdbc.Connection")
125 
126 // --------------------------------------------------------------------------------
createStatement()127 Reference< XStatement > SAL_CALL OConnection::createStatement(  ) throw(SQLException, RuntimeException)
128 {
129 	::osl::MutexGuard aGuard( m_aMutex );
130 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
131 
132 	// create a statement
133 	// the statement can only be executed once
134 	Reference< XStatement > xReturn = new OStatement(this);
135 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
136 	return xReturn;
137 }
138 // --------------------------------------------------------------------------------
prepareStatement(const::rtl::OUString & _sSql)139 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException)
140 {
141 	::osl::MutexGuard aGuard( m_aMutex );
142 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
143 
144 	// the pre
145 	if(m_aTypeInfo.empty())
146 		buildTypeInfo();
147 
148 	// create a statement
149 	// the statement can only be executed more than once
150 	Reference< XPreparedStatement > xReturn = new OPreparedStatement(this,m_aTypeInfo,_sSql);
151 	m_aStatements.push_back(WeakReferenceHelper(xReturn));
152 	return xReturn;
153 }
154 // --------------------------------------------------------------------------------
prepareCall(const::rtl::OUString & _sSql)155 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException)
156 {
157 	::osl::MutexGuard aGuard( m_aMutex );
158 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
159 
160 	// not implemented yet :-) a task to do
161 	return NULL;
162 }
163 // --------------------------------------------------------------------------------
nativeSQL(const::rtl::OUString & _sSql)164 ::rtl::OUString SAL_CALL OConnection::nativeSQL( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException)
165 {
166 	::osl::MutexGuard aGuard( m_aMutex );
167 	// when you need to transform SQL92 to you driver specific you can do it here
168 
169 	return _sSql;
170 }
171 // --------------------------------------------------------------------------------
setAutoCommit(sal_Bool autoCommit)172 void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) throw(SQLException, RuntimeException)
173 {
174 	::osl::MutexGuard aGuard( m_aMutex );
175 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
176 	// here you  have to set your commit mode please have a look at the jdbc documentation to get a clear explanation
177 }
178 // --------------------------------------------------------------------------------
getAutoCommit()179 sal_Bool SAL_CALL OConnection::getAutoCommit(  ) throw(SQLException, RuntimeException)
180 {
181 	::osl::MutexGuard aGuard( m_aMutex );
182 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
183 	// you have to distinguish which if you are in autocommit mode or not
184 	// at normal case true should be fine here
185 
186 	return sal_True;
187 }
188 // --------------------------------------------------------------------------------
commit()189 void SAL_CALL OConnection::commit(  ) throw(SQLException, RuntimeException)
190 {
191 	::osl::MutexGuard aGuard( m_aMutex );
192 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
193 
194 	// when you database does support transactions you should commit here
195 }
196 // --------------------------------------------------------------------------------
rollback()197 void SAL_CALL OConnection::rollback(  ) throw(SQLException, RuntimeException)
198 {
199 	::osl::MutexGuard aGuard( m_aMutex );
200 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
201 
202 
203 	// same as commit but for the other case
204 }
205 // --------------------------------------------------------------------------------
isClosed()206 sal_Bool SAL_CALL OConnection::isClosed(  ) throw(SQLException, RuntimeException)
207 {
208 	::osl::MutexGuard aGuard( m_aMutex );
209 
210 	// just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
211 	return OConnection_BASE::rBHelper.bDisposed;
212 }
213 // --------------------------------------------------------------------------------
getMetaData()214 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData(  ) throw(SQLException, RuntimeException)
215 {
216 	::osl::MutexGuard aGuard( m_aMutex );
217 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
218 
219 	// here we have to create the class with biggest interface
220 	// The answer is 42 :-)
221 	Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
222 	if(!xMetaData.is())
223 	{
224 		xMetaData = new ODatabaseMetaData(this); // need the connection because it can return it
225 		m_xMetaData = xMetaData;
226 	}
227 
228 	return xMetaData;
229 }
230 // --------------------------------------------------------------------------------
setReadOnly(sal_Bool readOnly)231 void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) throw(SQLException, RuntimeException)
232 {
233 	::osl::MutexGuard aGuard( m_aMutex );
234 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
235 
236 	// set you connection to readonly
237 }
238 // --------------------------------------------------------------------------------
isReadOnly()239 sal_Bool SAL_CALL OConnection::isReadOnly(  ) throw(SQLException, RuntimeException)
240 {
241 	::osl::MutexGuard aGuard( m_aMutex );
242 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
243 
244 	// return if your connection to readonly
245 	return sal_False;
246 }
247 // --------------------------------------------------------------------------------
setCatalog(const::rtl::OUString & catalog)248 void SAL_CALL OConnection::setCatalog( const ::rtl::OUString& catalog ) throw(SQLException, RuntimeException)
249 {
250 	::osl::MutexGuard aGuard( m_aMutex );
251 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
252 
253 	// if your database doesn't work with catalogs you go to next method otherwise you kjnow what to do
254 }
255 // --------------------------------------------------------------------------------
getCatalog()256 ::rtl::OUString SAL_CALL OConnection::getCatalog(  ) throw(SQLException, RuntimeException)
257 {
258 	::osl::MutexGuard aGuard( m_aMutex );
259 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
260 
261 
262 	// return your current catalog
263 	return ::rtl::OUString();
264 }
265 // --------------------------------------------------------------------------------
setTransactionIsolation(sal_Int32 level)266 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 level ) throw(SQLException, RuntimeException)
267 {
268 	::osl::MutexGuard aGuard( m_aMutex );
269 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
270 
271 	// set your isolation level
272 	// please have a look at @see com.sun.star.sdbc.TransactionIsolation
273 }
274 // --------------------------------------------------------------------------------
getTransactionIsolation()275 sal_Int32 SAL_CALL OConnection::getTransactionIsolation(  ) throw(SQLException, RuntimeException)
276 {
277 	::osl::MutexGuard aGuard( m_aMutex );
278 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
279 
280 
281 	// please have a look at @see com.sun.star.sdbc.TransactionIsolation
282 	return TransactionIsolation::NONE;
283 }
284 // --------------------------------------------------------------------------------
getTypeMap()285 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getTypeMap(  ) throw(SQLException, RuntimeException)
286 {
287 	::osl::MutexGuard aGuard( m_aMutex );
288 	checkDisposed(OConnection_BASE::rBHelper.bDisposed);
289 
290 	// if your driver has special database types you can return it here
291 
292 	return NULL;
293 }
294 // --------------------------------------------------------------------------------
setTypeMap(const Reference<::com::sun::star::container::XNameAccess> & typeMap)295 void SAL_CALL OConnection::setTypeMap( const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException)
296 {
297 	// the other way around
298 }
299 // --------------------------------------------------------------------------------
300 // XCloseable
close()301 void SAL_CALL OConnection::close(  ) throw(SQLException, RuntimeException)
302 {
303 	// we just dispose us
304 	{
305 		::osl::MutexGuard aGuard( m_aMutex );
306 		checkDisposed(OConnection_BASE::rBHelper.bDisposed);
307 
308 	}
309 	dispose();
310 }
311 // --------------------------------------------------------------------------------
312 // XWarningsSupplier
getWarnings()313 Any SAL_CALL OConnection::getWarnings(  ) throw(SQLException, RuntimeException)
314 {
315 	// when you collected some warnings -> return it
316 	return Any();
317 }
318 // --------------------------------------------------------------------------------
clearWarnings()319 void SAL_CALL OConnection::clearWarnings(  ) throw(SQLException, RuntimeException)
320 {
321 	// you should clear your collected warnings here
322 }
323 //--------------------------------------------------------------------
buildTypeInfo()324 void OConnection::buildTypeInfo() throw( SQLException)
325 {
326 	::osl::MutexGuard aGuard( m_aMutex );
327 
328 	Reference< XResultSet> xRs = getMetaData ()->getTypeInfo ();
329 	Reference< XRow> xRow(xRs,UNO_QUERY);
330 	// Information for a single SQL type
331 
332 	// Loop on the result set until we reach end of file
333 
334 	while (xRs->next ())
335 	{
336 		OTypeInfo aInfo;
337 		aInfo.aTypeName			= xRow->getString	(1);
338 		aInfo.nType				= xRow->getShort	(2);
339 		aInfo.nPrecision		= xRow->getInt		(3);
340 		aInfo.aLiteralPrefix	= xRow->getString	(4);
341 		aInfo.aLiteralSuffix	= xRow->getString	(5);
342 		aInfo.aCreateParams		= xRow->getString	(6);
343 		aInfo.bNullable			= xRow->getBoolean	(7) == ColumnValue::NULLABLE;
344 		aInfo.bCaseSensitive	= xRow->getBoolean	(8);
345 		aInfo.nSearchType		= xRow->getShort	(9);
346 		aInfo.bUnsigned			= xRow->getBoolean	(10);
347 		aInfo.bCurrency			= xRow->getBoolean	(11);
348 		aInfo.bAutoIncrement	= xRow->getBoolean	(12);
349 		aInfo.aLocalTypeName	= xRow->getString	(13);
350 		aInfo.nMinimumScale		= xRow->getShort	(14);
351 		aInfo.nMaximumScale		= xRow->getShort	(15);
352 		aInfo.nNumPrecRadix		= (sal_Int16)xRow->getInt(18);
353 
354 
355 
356 		// Now that we have the type info, save it
357 		// in the Hashtable if we don't already have an
358 		// entry for this SQL type.
359 
360 		m_aTypeInfo.push_back(aInfo);
361 	}
362 
363 	// Close the result set/statement.
364 
365 	Reference< XCloseable> xClose(xRs,UNO_QUERY);
366 	xClose->close();
367 }
368 //------------------------------------------------------------------------------
disposing()369 void OConnection::disposing()
370 {
371 	// we noticed that we should be destroied in near future so we have to dispose our statements
372 	::osl::MutexGuard aGuard(m_aMutex);
373 
374 	for (OWeakRefArray::iterator i = m_aStatements.begin(); m_aStatements.end() != i; ++i)
375 	{
376 		Reference< XComponent > xComp(i->get(), UNO_QUERY);
377 		if (xComp.is())
378 			xComp->dispose();
379 	}
380 	m_aStatements.clear();
381 
382 	m_bClosed	= sal_True;
383 	m_xMetaData = ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XDatabaseMetaData>();
384 
385 	dispose_ChildImpl();
386 	OConnection_BASE::disposing();
387 }
388 // -----------------------------------------------------------------------------
389 
390 
391 
392