xref: /AOO41X/main/odk/examples/DevelopersGuide/Database/DriverSkeleton/SConnection.cxx (revision 34dd1e2512dbacb6a9a7e4c7f17b9296daa8eff3)
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 taht 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