1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
7 * Copyright 2000, 2010 Oracle and/or its affiliates.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *************************************************************************/
36 #include "SConnection.hxx"
38 #include "SDatabaseMetaData.hxx"
39 #include "SDriver.hxx"
40 #include "SStatement.hxx"
41 #include "SPreparedStatement.hxx"
42 #include <com/sun/star/sdbc/ColumnValue.hpp>
43 #include <com/sun/star/sdbc/XRow.hpp>
44 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
47 using namespace connectivity::skeleton
;
50 using namespace com::sun::star::uno
;
51 using namespace com::sun::star::lang
;
52 using namespace com::sun::star::beans
;
53 using namespace com::sun::star::sdbc
;
55 OConnection::OConnection(SkeletonDriver
* _pDriver
)
56 : OSubComponent
<OConnection
, OConnection_BASE
>((::cppu::OWeakObject
*)_pDriver
, this),
57 OMetaConnection_BASE(m_aMutex
),
61 m_bUseCatalog(sal_False
),
62 m_bUseOldDateFormat(sal_False
)
67 OConnection::~OConnection()
75 void SAL_CALL
OConnection::release() throw()
81 void OConnection::construct(const ::rtl::OUString
& url
,const Sequence
< PropertyValue
>& info
) throw(SQLException
)
83 osl_atomic_increment( &m_refCount
);
85 // some example code how to get the information out of the sequence
87 sal_Int32 nLen
= url
.indexOf(':');
88 nLen
= url
.indexOf(':',nLen
+1);
89 ::rtl::OUString
aDSN("DSN="), aUID
, aPWD
, aSysDrvSettings
;
90 aDSN
+= url
.copy(nLen
+1);
92 const char* pUser
= "user";
93 const char* pTimeout
= "Timeout";
94 const char* pSilent
= "Silent";
95 const char* pPwd
= "password";
96 const char* pUseCatalog
= "UseCatalog";
97 const char* pSysDrv
= "SystemDriverSettings";
99 sal_Int32 nTimeout
= 20;
100 sal_Bool bSilent
= sal_True
;
101 const PropertyValue
*pBegin
= info
.getConstArray();
102 const PropertyValue
*pEnd
= pBegin
+ info
.getLength();
103 for(;pBegin
!= pEnd
;++pBegin
)
105 if(pBegin
->Name
.equalsAscii(pTimeout
))
106 pBegin
->Value
>>= nTimeout
;
107 else if(pBegin
->Name
.equalsAscii(pSilent
))
108 pBegin
->Value
>>= bSilent
;
109 else if(pBegin
->Name
.equalsAscii(pUser
))
111 pBegin
->Value
>>= aUID
;
112 aDSN
+= ";UID=" + aUID
;
114 else if(pBegin
->Name
.equalsAscii(pPwd
))
116 pBegin
->Value
>>= aPWD
;
117 aDSN
+= ";PWD=" + aPWD
;
119 else if(pBegin
->Name
.equalsAscii(pUseCatalog
))
121 pBegin
->Value
>>= m_bUseCatalog
;
123 else if(pBegin
->Name
.equalsAscii(pSysDrv
))
125 pBegin
->Value
>>= aSysDrvSettings
;
127 aDSN
+= aSysDrvSettings
;
132 osl_atomic_decrement( &m_refCount
);
136 IMPLEMENT_SERVICE_INFO(OConnection
, "com.sun.star.sdbc.drivers.skeleton.OConnection", "com.sun.star.sdbc.Connection")
139 Reference
< XStatement
> SAL_CALL
OConnection::createStatement( ) throw(SQLException
, RuntimeException
)
141 ::osl::MutexGuard
aGuard( m_aMutex
);
142 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
144 // create a statement
145 // the statement can only be executed once
146 Reference
< XStatement
> xReturn
= new OStatement(this);
147 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
151 Reference
< XPreparedStatement
> SAL_CALL
OConnection::prepareStatement( const ::rtl::OUString
& _sSql
) throw(SQLException
, RuntimeException
)
153 ::osl::MutexGuard
aGuard( m_aMutex
);
154 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
157 if(m_aTypeInfo
.empty())
160 // create a statement
161 // the statement can only be executed more than once
162 Reference
< XPreparedStatement
> xReturn
= new OPreparedStatement(this,m_aTypeInfo
,_sSql
);
163 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
167 Reference
< XPreparedStatement
> SAL_CALL
OConnection::prepareCall( const ::rtl::OUString
& _sSql
) throw(SQLException
, RuntimeException
)
169 ::osl::MutexGuard
aGuard( m_aMutex
);
170 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
172 // not implemented yet :-) a task to do
176 ::rtl::OUString SAL_CALL
OConnection::nativeSQL( const ::rtl::OUString
& _sSql
) throw(SQLException
, RuntimeException
)
178 ::osl::MutexGuard
aGuard( m_aMutex
);
179 // when you need to transform SQL92 to you driver specific you can do it here
184 void SAL_CALL
OConnection::setAutoCommit( sal_Bool autoCommit
) throw(SQLException
, RuntimeException
)
186 ::osl::MutexGuard
aGuard( m_aMutex
);
187 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
188 // here you have to set your commit mode please have a look at the jdbc documentation to get a clear explanation
191 sal_Bool SAL_CALL
OConnection::getAutoCommit( ) throw(SQLException
, RuntimeException
)
193 ::osl::MutexGuard
aGuard( m_aMutex
);
194 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
195 // you have to distinguish which if you are in autocommit mode or not
196 // at normal case true should be fine here
201 void SAL_CALL
OConnection::commit( ) throw(SQLException
, RuntimeException
)
203 ::osl::MutexGuard
aGuard( m_aMutex
);
204 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
206 // when your database does support transactions you should commit here
209 void SAL_CALL
OConnection::rollback( ) throw(SQLException
, RuntimeException
)
211 ::osl::MutexGuard
aGuard( m_aMutex
);
212 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
215 // same as commit but for the other case
218 sal_Bool SAL_CALL
OConnection::isClosed( ) throw(SQLException
, RuntimeException
)
220 ::osl::MutexGuard
aGuard( m_aMutex
);
222 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
223 return OConnection_BASE::rBHelper
.bDisposed
;
226 Reference
< XDatabaseMetaData
> SAL_CALL
OConnection::getMetaData( ) throw(SQLException
, RuntimeException
)
228 ::osl::MutexGuard
aGuard( m_aMutex
);
229 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
231 // here we have to create the class with biggest interface
232 // The answer is 42 :-)
233 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
236 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
237 m_xMetaData
= xMetaData
;
243 void SAL_CALL
OConnection::setReadOnly( sal_Bool readOnly
) throw(SQLException
, RuntimeException
)
245 ::osl::MutexGuard
aGuard( m_aMutex
);
246 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
248 // set you connection to readonly
251 sal_Bool SAL_CALL
OConnection::isReadOnly( ) throw(SQLException
, RuntimeException
)
253 ::osl::MutexGuard
aGuard( m_aMutex
);
254 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
256 // return if your connection to readonly
260 void SAL_CALL
OConnection::setCatalog( const ::rtl::OUString
& catalog
) throw(SQLException
, RuntimeException
)
262 ::osl::MutexGuard
aGuard( m_aMutex
);
263 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
265 // if your database doesn't work with catalogs you go to next method otherwise you know what to do
268 ::rtl::OUString SAL_CALL
OConnection::getCatalog( ) throw(SQLException
, RuntimeException
)
270 ::osl::MutexGuard
aGuard( m_aMutex
);
271 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
274 // return your current catalog
275 return ::rtl::OUString();
278 void SAL_CALL
OConnection::setTransactionIsolation( sal_Int32 level
) throw(SQLException
, RuntimeException
)
280 ::osl::MutexGuard
aGuard( m_aMutex
);
281 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
283 /// set your isolation level
284 /// please have a look at @see com.sun.star.sdbc.TransactionIsolation
287 sal_Int32 SAL_CALL
OConnection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
)
289 ::osl::MutexGuard
aGuard( m_aMutex
);
290 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
293 // please have a look at @see com.sun.star.sdbc.TransactionIsolation
294 return TransactionIsolation::NONE
;
297 Reference
< ::com::sun::star::container::XNameAccess
> SAL_CALL
OConnection::getTypeMap( ) throw(SQLException
, RuntimeException
)
299 ::osl::MutexGuard
aGuard( m_aMutex
);
300 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
302 // if your driver has special database types you can return it here
307 void SAL_CALL
OConnection::setTypeMap( const Reference
< ::com::sun::star::container::XNameAccess
>& typeMap
) throw(SQLException
, RuntimeException
)
309 // the other way around
313 void SAL_CALL
OConnection::close( ) throw(SQLException
, RuntimeException
)
315 // we just dispose us
317 ::osl::MutexGuard
aGuard( m_aMutex
);
318 checkDisposed(OConnection_BASE::rBHelper
.bDisposed
);
325 Any SAL_CALL
OConnection::getWarnings( ) throw(SQLException
, RuntimeException
)
327 // when you collected some warnings -> return it
331 void SAL_CALL
OConnection::clearWarnings( ) throw(SQLException
, RuntimeException
)
333 // you should clear your collected warnings here
336 void OConnection::buildTypeInfo() throw( SQLException
)
338 ::osl::MutexGuard
aGuard( m_aMutex
);
340 Reference
< XResultSet
> xRs
= getMetaData ()->getTypeInfo ();
341 Reference
< XRow
> xRow(xRs
,UNO_QUERY
);
342 // Information for a single SQL type
344 // Loop on the result set until we reach end of file
349 aInfo
.aTypeName
= xRow
->getString (1);
350 aInfo
.nType
= xRow
->getShort (2);
351 aInfo
.nPrecision
= xRow
->getInt (3);
352 aInfo
.aLiteralPrefix
= xRow
->getString (4);
353 aInfo
.aLiteralSuffix
= xRow
->getString (5);
354 aInfo
.aCreateParams
= xRow
->getString (6);
355 aInfo
.bNullable
= xRow
->getBoolean (7);
356 aInfo
.bCaseSensitive
= xRow
->getBoolean (8);
357 aInfo
.nSearchType
= xRow
->getShort (9);
358 aInfo
.bUnsigned
= xRow
->getBoolean (10);
359 aInfo
.bCurrency
= xRow
->getBoolean (11);
360 aInfo
.bAutoIncrement
= xRow
->getBoolean (12);
361 aInfo
.aLocalTypeName
= xRow
->getString (13);
362 aInfo
.nMinimumScale
= xRow
->getShort (14);
363 aInfo
.nMaximumScale
= xRow
->getShort (15);
364 aInfo
.nNumPrecRadix
= (sal_Int16
)xRow
->getInt(18);
367 // Now that we have the type info, save it
368 // in the Hashtable if we don't already have an
369 // entry for this SQL type.
371 m_aTypeInfo
.push_back(aInfo
);
374 // Close the result set/statement.
376 Reference
< XCloseable
> xClose(xRs
,UNO_QUERY
);
380 void OConnection::disposing()
382 // we noticed that we should be destroyed in near future so we have to dispose our statements
383 ::osl::MutexGuard
aGuard(m_aMutex
);
385 for (OWeakRefArray::iterator i
= m_aStatements
.begin(); m_aStatements
.end() != i
; ++i
)
387 Reference
< XComponent
> xComp(i
->get(), UNO_QUERY
);
391 m_aStatements
.clear();
393 m_bClosed
= sal_True
;
394 m_xMetaData
= ::com::sun::star::uno::WeakReference
< ::com::sun::star::sdbc::XDatabaseMetaData
>();
397 OConnection_BASE::disposing();
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */