1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "Catalog.hxx"
21 #include "Connection.hxx"
22 #include "DatabaseMetaData.hxx"
24 #include "PreparedStatement.hxx"
25 #include "Statement.hxx"
31 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
32 #include <com/sun/star/embed/ElementModes.hpp>
33 #include <com/sun/star/frame/Desktop.hpp>
34 #include <com/sun/star/frame/FrameSearchFlag.hpp>
35 #include <com/sun/star/frame/XController.hpp>
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/frame/XFrames.hpp>
38 #include <com/sun/star/frame/XModel.hpp>
39 #include <com/sun/star/io/TempFile.hpp>
40 #include <com/sun/star/io/XStream.hpp>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/lang/EventObject.hpp>
43 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
44 #include <com/sun/star/sdbc/ColumnValue.hpp>
45 #include <com/sun/star/sdbc/XRow.hpp>
46 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
47 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
48 #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
50 #include <connectivity/dbexception.hxx>
51 #include <connectivity/sqlparse.hxx>
52 #include <resource/common_res.hrc>
53 #include <resource/hsqldb_res.hrc>
54 #include <resource/sharedresources.hxx>
56 #include <comphelper/processfactory.hxx>
57 #include <comphelper/storagehelper.hxx>
58 #include <cppuhelper/exc_hlp.hxx>
59 #include <unotools/tempfile.hxx>
60 #include <unotools/localfilehelper.hxx>
61 #include <unotools/ucbstreamhelper.hxx>
63 #include <rtl/strbuf.hxx>
66 // for ADD_SPB_NUMERIC
67 #pragma warning(disable: 4310) // cast truncates data
70 using namespace connectivity::firebird
;
71 using namespace connectivity
;
73 using namespace ::osl
;
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::beans
;
77 using namespace ::com::sun::star::container
;
78 using namespace ::com::sun::star::document
;
79 using namespace ::com::sun::star::embed
;
80 using namespace ::com::sun::star::frame
;
81 using namespace ::com::sun::star::io
;
82 using namespace ::com::sun::star::lang
;
83 using namespace ::com::sun::star::sdbc
;
84 using namespace ::com::sun::star::sdbcx
;
85 using namespace ::com::sun::star::uno
;
88 * Location within the .odb that an embedded .fdb will be stored.
89 * Only relevant for embedded dbs.
91 static const OUStringLiteral
our_sFDBLocation( "firebird.fdb" );
93 * Older version of LO may store the database in a .fdb file
95 static const OUStringLiteral
our_sFBKLocation( "firebird.fbk" );
97 Connection::Connection(FirebirdDriver
* _pDriver
)
98 : Connection_BASE(m_aMutex
)
99 , OSubComponent
<Connection
, Connection_BASE
>(static_cast<cppu::OWeakObject
*>(_pDriver
), this)
100 , m_xDriver(_pDriver
)
103 , m_bIsEmbedded(false)
104 , m_xEmbeddedStorage(nullptr)
106 , m_bIsAutoCommit(false)
107 , m_bIsReadOnly(false)
108 , m_aTransactionIsolation(TransactionIsolation::REPEATABLE_READ
)
109 #if SAL_TYPES_SIZEOFPOINTER == 8
111 , m_aTransactionHandle(0)
113 , m_aDBHandle(nullptr)
114 , m_aTransactionHandle(nullptr)
116 , m_xCatalog(nullptr)
117 , m_xMetaData(nullptr)
122 Connection::~Connection()
128 void SAL_CALL
Connection::release() throw()
133 struct ConnectionGuard
135 oslInterlockedCount
& m_refCount
;
136 explicit ConnectionGuard(oslInterlockedCount
& refCount
)
137 : m_refCount(refCount
)
139 osl_atomic_increment(&m_refCount
);
143 osl_atomic_decrement(&m_refCount
);
147 void Connection::construct(const ::rtl::OUString
& url
, const Sequence
< PropertyValue
>& info
)
148 throw (SQLException
, RuntimeException
, std::exception
)
150 ConnectionGuard
aGuard(m_refCount
);
154 m_sConnectionURL
= url
;
156 bool bIsNewDatabase
= false;
157 // the database may be stored as an
158 // fdb file in older versions
159 bool bIsFdbStored
= false;
160 OUString aStorageURL
;
161 if (url
== "sdbc:embedded:firebird")
163 m_bIsEmbedded
= true;
165 const PropertyValue
* pIter
= info
.getConstArray();
166 const PropertyValue
* pEnd
= pIter
+ info
.getLength();
168 for (;pIter
!= pEnd
; ++pIter
)
170 if ( pIter
->Name
== "Storage" )
172 m_xEmbeddedStorage
.set(pIter
->Value
,UNO_QUERY
);
174 else if ( pIter
->Name
== "URL" )
176 pIter
->Value
>>= aStorageURL
;
178 else if ( pIter
->Name
== "Document" )
180 pIter
->Value
>>= m_xParentDocument
;
184 if ( !m_xEmbeddedStorage
.is() )
186 ::connectivity::SharedResources aResources
;
187 const OUString sMessage
= aResources
.getResourceString(STR_NO_STORAGE
);
188 ::dbtools::throwGenericSQLException(sMessage
,*this);
191 bIsNewDatabase
= !m_xEmbeddedStorage
->hasElements();
193 m_pDatabaseFileDir
.reset(new ::utl::TempFile(nullptr, true));
194 m_pDatabaseFileDir
->EnableKillingFile();
195 m_sFirebirdURL
= m_pDatabaseFileDir
->GetFileName() + "/firebird.fdb";
196 m_sFBKPath
= m_pDatabaseFileDir
->GetFileName() + "/firebird.fbk";
198 SAL_INFO("connectivity.firebird", "Temporary .fdb location: " << m_sFirebirdURL
);
202 if (m_xEmbeddedStorage
->hasByName(our_sFBKLocation
) &&
203 m_xEmbeddedStorage
->isStreamElement(our_sFBKLocation
))
205 SAL_INFO("connectivity.firebird", "Extracting* .fbk from .odb" );
206 loadDatabaseFile(our_sFBKLocation
, m_sFBKPath
);
208 else if(m_xEmbeddedStorage
->hasByName(our_sFDBLocation
) &&
209 m_xEmbeddedStorage
->isStreamElement(our_sFDBLocation
))
211 SAL_INFO("connectivity.firebird", "Found .fdb instead of .fbk");
213 loadDatabaseFile(our_sFDBLocation
, m_sFirebirdURL
);
217 ::connectivity::SharedResources aResources
;
218 // TODO FIXME: this does _not_ look like the right error message
219 const OUString sMessage
= aResources
.getResourceString(STR_ERROR_NEW_VERSION
);
220 ::dbtools::throwGenericSQLException(sMessage
,*this);
224 // TODO: Get DB properties from XML
227 // External file AND/OR remote connection
228 else if (url
.startsWith("sdbc:firebird:"))
230 m_sFirebirdURL
= url
.copy(OUString("sdbc:firebird:").getLength());
231 if (m_sFirebirdURL
.startsWith("file://"))
234 uno::Reference
< ucb::XSimpleFileAccess
> xFileAccess(
235 ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext()),
237 if (!xFileAccess
->exists(m_sFirebirdURL
))
238 bIsNewDatabase
= true;
240 m_sFirebirdURL
= m_sFirebirdURL
.copy(OUString("file://").getLength());
244 char dpbBuffer
[1 + 3 + 257 + 257 + 5 ]; // Expand as needed
248 char userName
[256] = "";
249 char userPassword
[256] = "";
252 *dpb
++ = isc_dpb_version1
;
254 *dpb
++ = isc_dpb_sql_dialect
;
255 *dpb
++ = 1; // 1 byte long
256 *dpb
++ = FIREBIRD_SQL_DIALECT
;
258 // set UTF8 as default character set
259 const char sCharset
[] = "UTF8";
260 *dpb
++ = isc_dpb_set_db_charset
;
261 int nCharsetLength
= sizeof(sCharset
) - 1;
262 *dpb
++ = (char) nCharsetLength
;
263 strcpy(dpb
, sCharset
);
264 dpb
+= nCharsetLength
;
266 // Do any more dpbBuffer additions here
268 if (m_bIsEmbedded
|| m_bIsFile
)
270 strcpy(userName
,"sysdba");
271 strcpy(userPassword
,"masterkey");
275 // TODO: parse password from connection string as needed?
278 if (strlen(userName
))
280 int nUsernameLength
= strlen(userName
);
281 *dpb
++ = isc_dpb_user_name
;
282 *dpb
++ = (char) nUsernameLength
;
283 strcpy(dpb
, userName
);
284 dpb
+= nUsernameLength
;
287 if (strlen(userPassword
))
289 int nPasswordLength
= strlen(userPassword
);
290 *dpb
++ = isc_dpb_password
;
291 *dpb
++ = (char) nPasswordLength
;
292 strcpy(dpb
, userPassword
);
293 dpb
+= nPasswordLength
;
296 dpbLength
= dpb
- dpbBuffer
;
299 ISC_STATUS_ARRAY status
; /* status vector */
303 aErr
= isc_create_database(status
,
304 m_sFirebirdURL
.getLength(),
305 OUStringToOString(m_sFirebirdURL
,RTL_TEXTENCODING_UTF8
).getStr(),
312 evaluateStatusVector(status
, "isc_create_database", *this);
317 if (m_bIsEmbedded
&& !bIsFdbStored
) // We need to restore the .fbk first
319 runBackupService(isc_action_svc_restore
);
322 aErr
= isc_attach_database(status
,
323 m_sFirebirdURL
.getLength(),
324 OUStringToOString(m_sFirebirdURL
, RTL_TEXTENCODING_UTF8
).getStr(),
330 evaluateStatusVector(status
, "isc_attach_database", *this);
334 if (m_bIsEmbedded
) // Add DocumentEventListener to save the .fdb as needed
336 // We need to attach as a document listener in order to be able to store
337 // the temporary db back into the .odb when saving
338 uno::Reference
<XDocumentEventBroadcaster
> xBroadcaster(m_xParentDocument
, UNO_QUERY
);
340 if (xBroadcaster
.is())
341 xBroadcaster
->addDocumentEventListener(this);
346 catch (const Exception
&)
350 catch (const std::exception
&)
354 catch (...) // const Firebird::Exception& firebird throws this, but doesn't install the fb_exception.h that declares it
357 throw std::runtime_error("Generic Firebird::Exception");
361 void Connection::notifyDatabaseModified()
363 if (m_xParentDocument
.is()) // Only true in embedded mode
364 m_xParentDocument
->setModified(true);
367 //----- XServiceInfo ---------------------------------------------------------
368 IMPLEMENT_SERVICE_INFO(Connection
, "com.sun.star.sdbc.drivers.firebird.Connection",
369 "com.sun.star.sdbc.Connection")
371 Reference
< XBlob
> Connection::createBlob(ISC_QUAD
* pBlobId
)
372 throw(SQLException
, RuntimeException
)
374 MutexGuard
aGuard(m_aMutex
);
375 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
377 Reference
< XBlob
> xReturn
= new Blob(&m_aDBHandle
,
378 &m_aTransactionHandle
,
381 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
385 Reference
< XClob
> Connection::createClob(ISC_QUAD
* pBlobId
)
386 throw(SQLException
, RuntimeException
)
388 MutexGuard
aGuard(m_aMutex
);
389 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
391 Reference
< XClob
> xReturn
= new Clob(&m_aDBHandle
,
392 &m_aTransactionHandle
,
395 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
400 //----- XConnection ----------------------------------------------------------
401 Reference
< XStatement
> SAL_CALL
Connection::createStatement( )
402 throw(SQLException
, RuntimeException
, std::exception
)
404 MutexGuard
aGuard( m_aMutex
);
405 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
408 if(m_aTypeInfo
.empty())
411 // create a statement
412 // the statement can only be executed once
413 Reference
< XStatement
> xReturn
= new OStatement(this);
414 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
418 OUString
Connection::transformPreparedStatement(const OUString
& _sSQL
)
420 OUString
sSqlStatement (_sSQL
);
423 OSQLParser
aParser( m_xDriver
->getContext() );
424 OUString sErrorMessage
;
426 OSQLParseNode
* pNode
= aParser
.parseTree(sErrorMessage
,_sSQL
);
428 { // special handling for parameters
429 OSQLParseNode::substituteParameterNames(pNode
);
430 pNode
->parseNodeToStr( sNewSql
, this );
432 sSqlStatement
= sNewSql
;
435 catch(const Exception
&)
437 SAL_WARN("connectivity.firebird", "failed to remove named parameters from '" << _sSQL
<< "'");
439 return sSqlStatement
;
442 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareStatement(
443 const OUString
& _sSql
)
444 throw(SQLException
, RuntimeException
, std::exception
)
446 SAL_INFO("connectivity.firebird", "prepareStatement() "
447 "called with sql: " << _sSql
);
448 MutexGuard
aGuard(m_aMutex
);
449 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
451 if(m_aTypeInfo
.empty())
454 OUString
sSqlStatement (transformPreparedStatement( _sSql
));
456 Reference
< XPreparedStatement
> xReturn
= new OPreparedStatement(this,
458 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
463 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareCall(
464 const OUString
& _sSql
) throw(SQLException
, RuntimeException
, std::exception
)
466 SAL_INFO("connectivity.firebird", "prepareCall(). "
469 MutexGuard
aGuard( m_aMutex
);
470 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
472 // OUString sSqlStatement (transformPreparedStatement( _sSql ));
474 // not implemented yet :-) a task to do
478 OUString SAL_CALL
Connection::nativeSQL( const OUString
& _sSql
)
479 throw(SQLException
, RuntimeException
, std::exception
)
481 MutexGuard
aGuard( m_aMutex
);
482 // We do not need to adapt the SQL for Firebird atm.
486 void SAL_CALL
Connection::setAutoCommit( sal_Bool autoCommit
)
487 throw(SQLException
, RuntimeException
, std::exception
)
489 MutexGuard
aGuard( m_aMutex
);
490 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
492 m_bIsAutoCommit
= autoCommit
;
494 if (m_aTransactionHandle
)
500 sal_Bool SAL_CALL
Connection::getAutoCommit() throw(SQLException
, RuntimeException
, std::exception
)
502 MutexGuard
aGuard( m_aMutex
);
503 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
505 return m_bIsAutoCommit
;
508 void Connection::setupTransaction()
511 MutexGuard
aGuard( m_aMutex
);
512 ISC_STATUS status_vector
[20];
514 // TODO: is this sensible? If we have changed parameters then transaction
516 if (m_aTransactionHandle
)
519 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
522 char aTransactionIsolation
= 0;
523 switch (m_aTransactionIsolation
)
525 // TODO: confirm that these are correct.
526 case(TransactionIsolation::READ_UNCOMMITTED
):
527 aTransactionIsolation
= isc_tpb_concurrency
;
529 case(TransactionIsolation::READ_COMMITTED
):
530 aTransactionIsolation
= isc_tpb_read_committed
;
532 case(TransactionIsolation::REPEATABLE_READ
):
533 aTransactionIsolation
= isc_tpb_consistency
;
535 case(TransactionIsolation::SERIALIZABLE
):
536 aTransactionIsolation
= isc_tpb_consistency
;
539 assert( false ); // We must have a valid TransactionIsolation.
542 // You cannot pass an empty tpb parameter so we have to do some pointer
543 // arithmetic to avoid problems. (i.e. aTPB[x] = 0 is invalid)
547 *pTPB
++ = isc_tpb_version3
;
549 *pTPB
++ = isc_tpb_autocommit
;
550 *pTPB
++ = (!m_bIsReadOnly
? isc_tpb_write
: isc_tpb_read
);
551 *pTPB
++ = aTransactionIsolation
;
552 *pTPB
++ = isc_tpb_wait
;
554 isc_start_transaction(status_vector
,
555 &m_aTransactionHandle
,
558 pTPB
- aTPB
, // bytes used in TPB
561 evaluateStatusVector(status_vector
,
562 "isc_start_transaction",
566 isc_tr_handle
& Connection::getTransaction()
569 MutexGuard
aGuard( m_aMutex
);
570 if (!m_aTransactionHandle
)
574 return m_aTransactionHandle
;
577 void SAL_CALL
Connection::commit() throw(SQLException
, RuntimeException
, std::exception
)
579 MutexGuard
aGuard( m_aMutex
);
580 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
582 ISC_STATUS status_vector
[20];
584 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
587 isc_commit_transaction(status_vector
, &m_aTransactionHandle
);
588 evaluateStatusVector(status_vector
,
589 "isc_commit_transaction",
594 void Connection::loadDatabaseFile(const OUString
& srcLocation
, const OUString
& tmpLocation
)
596 Reference
< XStream
> xDBStream(m_xEmbeddedStorage
->openStreamElement(srcLocation
,
597 ElementModes::READ
));
599 uno::Reference
< ucb::XSimpleFileAccess2
> xFileAccess(
600 ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ),
602 if ( !xFileAccess
.is() )
604 ::connectivity::SharedResources aResources
;
605 // TODO FIXME: this does _not_ look like the right error message
606 const OUString sMessage
= aResources
.getResourceString(STR_ERROR_NEW_VERSION
);
607 ::dbtools::throwGenericSQLException(sMessage
,*this);
609 xFileAccess
->writeFile(tmpLocation
,xDBStream
->getInputStream());
612 isc_svc_handle
Connection::attachServiceManager()
614 ISC_STATUS_ARRAY aStatusVector
;
615 #if SAL_TYPES_SIZEOFPOINTER == 8
616 isc_svc_handle aServiceHandle
= 0;
618 isc_svc_handle aServiceHandle
= nullptr;
621 char aSPBBuffer
[256];
622 char* pSPB
= aSPBBuffer
;
623 *pSPB
++ = isc_spb_version
;
624 *pSPB
++ = isc_spb_current_version
;
625 *pSPB
++ = isc_spb_user_name
;
626 OUString
sUserName("SYSDBA");
627 char aLength
= (char) sUserName
.getLength();
630 OUStringToOString(sUserName
,
631 RTL_TEXTENCODING_UTF8
).getStr(),
634 // TODO: do we need ", isc_dpb_trusted_auth, 1, 1" -- probably not but ...
635 if (isc_service_attach(aStatusVector
,
636 0, // Denotes null-terminated string next
642 evaluateStatusVector(aStatusVector
,
643 "isc_service_attach",
647 return aServiceHandle
;
650 void Connection::detachServiceManager(isc_svc_handle aServiceHandle
)
652 ISC_STATUS_ARRAY aStatusVector
;
653 if (isc_service_detach(aStatusVector
,
656 evaluateStatusVector(aStatusVector
,
657 "isc_service_detach",
662 void Connection::runBackupService(const short nAction
)
664 assert(nAction
== isc_action_svc_backup
665 || nAction
== isc_action_svc_restore
);
667 ISC_STATUS_ARRAY aStatusVector
;
669 // convert paths to 8-Bit strings
670 OString sFDBPath
= OUStringToOString(m_sFirebirdURL
, RTL_TEXTENCODING_UTF8
);
671 OString sFBKPath
= OUStringToOString(m_sFBKPath
, RTL_TEXTENCODING_UTF8
);
674 OStringBuffer aRequest
; // byte array
677 aRequest
.append((char) nAction
);
679 aRequest
.append((char) isc_spb_dbname
); // .fdb
680 sal_uInt16 nFDBLength
= sFDBPath
.getLength();
681 aRequest
.append((char) (nFDBLength
& 0xFF)); // least significant byte first
682 aRequest
.append((char) ((nFDBLength
>> 8) & 0xFF));
683 aRequest
.append(sFDBPath
);
685 aRequest
.append((char) isc_spb_bkp_file
); // .fbk
686 sal_uInt16 nFBKLength
= sFBKPath
.getLength();
687 aRequest
.append((char) (nFBKLength
& 0xFF));
688 aRequest
.append((char) ((nFBKLength
>> 8) & 0xFF));
689 aRequest
.append(sFBKPath
);
691 if (nAction
== isc_action_svc_restore
)
693 aRequest
.append((char) isc_spb_options
); // 4-Byte bitmask
695 char * pOptions
= sOptions
;
696 ADD_SPB_NUMERIC(pOptions
, isc_spb_res_create
);
697 aRequest
.append(sOptions
, 4);
700 isc_svc_handle aServiceHandle
;
701 aServiceHandle
= attachServiceManager();
703 if (isc_service_start(aStatusVector
,
706 aRequest
.getLength(),
709 evaluateStatusVector(aStatusVector
, "isc_service_start", *this);
712 char aInfoSPB
= isc_info_svc_line
;
715 // query blocks until success or error
716 if(isc_service_query(aStatusVector
,
718 nullptr, // Reserved null
719 0,nullptr, // "send" spb -- size and spb -- not needed?
725 evaluateStatusVector(aStatusVector
, "isc_service_query", *this);
728 detachServiceManager(aServiceHandle
);
732 void SAL_CALL
Connection::rollback() throw(SQLException
, RuntimeException
, std::exception
)
734 MutexGuard
aGuard( m_aMutex
);
735 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
737 ISC_STATUS status_vector
[20];
739 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
741 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
745 sal_Bool SAL_CALL
Connection::isClosed( ) throw(SQLException
, RuntimeException
, std::exception
)
747 MutexGuard
aGuard( m_aMutex
);
749 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
750 return Connection_BASE::rBHelper
.bDisposed
;
753 Reference
< XDatabaseMetaData
> SAL_CALL
Connection::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
755 MutexGuard
aGuard( m_aMutex
);
756 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
758 // here we have to create the class with biggest interface
759 // The answer is 42 :-)
760 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
763 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
764 m_xMetaData
= xMetaData
;
770 void SAL_CALL
Connection::setReadOnly(sal_Bool readOnly
)
771 throw(SQLException
, RuntimeException
, std::exception
)
773 MutexGuard
aGuard( m_aMutex
);
774 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
776 m_bIsReadOnly
= readOnly
;
780 sal_Bool SAL_CALL
Connection::isReadOnly() throw(SQLException
, RuntimeException
, std::exception
)
782 MutexGuard
aGuard( m_aMutex
);
783 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
785 return m_bIsReadOnly
;
788 void SAL_CALL
Connection::setCatalog(const OUString
& /*catalog*/)
789 throw(SQLException
, RuntimeException
, std::exception
)
791 ::dbtools::throwFunctionNotSupportedSQLException("setCatalog", *this);
794 OUString SAL_CALL
Connection::getCatalog()
795 throw(SQLException
, RuntimeException
, std::exception
)
797 ::dbtools::throwFunctionNotSupportedSQLException("getCatalog", *this);
801 void SAL_CALL
Connection::setTransactionIsolation( sal_Int32 level
) throw(SQLException
, RuntimeException
, std::exception
)
803 MutexGuard
aGuard( m_aMutex
);
804 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
806 m_aTransactionIsolation
= level
;
810 sal_Int32 SAL_CALL
Connection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
, std::exception
)
812 MutexGuard
aGuard( m_aMutex
);
813 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
815 return m_aTransactionIsolation
;
818 Reference
< XNameAccess
> SAL_CALL
Connection::getTypeMap() throw(SQLException
, RuntimeException
, std::exception
)
820 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::getTypeMap", *this );
824 void SAL_CALL
Connection::setTypeMap(const Reference
< XNameAccess
>& typeMap
)
825 throw(SQLException
, RuntimeException
, std::exception
)
827 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
831 //----- XCloseable -----------------------------------------------------------
832 void SAL_CALL
Connection::close( ) throw(SQLException
, RuntimeException
, std::exception
)
834 // we just dispose us
836 MutexGuard
aGuard( m_aMutex
);
837 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
844 Any SAL_CALL
Connection::getWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
846 // when you collected some warnings -> return it
850 void SAL_CALL
Connection::clearWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
852 // you should clear your collected warnings here
855 // XDocumentEventListener
856 void SAL_CALL
Connection::documentEventOccured( const DocumentEvent
& Event
)
857 throw(RuntimeException
, std::exception
)
859 MutexGuard
aGuard(m_aMutex
);
864 if (Event
.EventName
== "OnSave" || Event
.EventName
== "OnSaveAs")
866 commit(); // Commit and close transaction
867 if ( m_bIsEmbedded
&& m_xEmbeddedStorage
.is() )
869 SAL_INFO("connectivity.firebird", "Writing .fbk from running db");
872 runBackupService(isc_action_svc_backup
);
874 catch (const SQLException
& e
)
876 auto a
= cppu::getCaughtException();
877 throw WrappedTargetRuntimeException(e
.Message
, e
.Context
, a
);
881 Reference
< XStream
> xDBStream(m_xEmbeddedStorage
->openStreamElement(our_sFBKLocation
,
882 ElementModes::WRITE
));
884 // TODO: verify the backup actually exists -- the backup service
885 // can fail without giving any sane error messages / telling us
887 using namespace ::comphelper
;
888 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
889 Reference
< XInputStream
> xInputStream
;
893 OStorageHelper::GetInputStreamFromURL(m_sFBKPath
, xContext
);
894 if (xInputStream
.is())
895 OStorageHelper::CopyInputToOutput( xInputStream
,
896 xDBStream
->getOutputStream());
898 // remove old fdb file if exists
899 uno::Reference
< ucb::XSimpleFileAccess
> xFileAccess(
900 ucb::SimpleFileAccess::create(xContext
),
902 if (xFileAccess
->exists(m_sFirebirdURL
))
903 xFileAccess
->kill(m_sFirebirdURL
);
910 void SAL_CALL
Connection::disposing(const EventObject
& /*rSource*/)
911 throw (RuntimeException
, std::exception
)
913 MutexGuard
aGuard( m_aMutex
);
915 m_xEmbeddedStorage
.clear();
918 void Connection::buildTypeInfo() throw( SQLException
)
920 MutexGuard
aGuard( m_aMutex
);
922 Reference
< XResultSet
> xRs
= getMetaData ()->getTypeInfo ();
923 Reference
< XRow
> xRow(xRs
,UNO_QUERY
);
924 // Information for a single SQL type
926 // Loop on the result set until we reach end of file
931 aInfo
.aTypeName
= xRow
->getString (1);
932 aInfo
.nType
= xRow
->getShort (2);
933 aInfo
.nPrecision
= xRow
->getInt (3);
934 aInfo
.aLiteralPrefix
= xRow
->getString (4);
935 aInfo
.aLiteralSuffix
= xRow
->getString (5);
936 aInfo
.aCreateParams
= xRow
->getString (6);
937 aInfo
.bNullable
= xRow
->getBoolean (7);
938 aInfo
.bCaseSensitive
= xRow
->getBoolean (8);
939 aInfo
.nSearchType
= xRow
->getShort (9);
940 aInfo
.bUnsigned
= xRow
->getBoolean (10);
941 aInfo
.bCurrency
= xRow
->getBoolean (11);
942 aInfo
.bAutoIncrement
= xRow
->getBoolean (12);
943 aInfo
.aLocalTypeName
= xRow
->getString (13);
944 aInfo
.nMinimumScale
= xRow
->getShort (14);
945 aInfo
.nMaximumScale
= xRow
->getShort (15);
946 aInfo
.nNumPrecRadix
= (sal_Int16
)xRow
->getInt(18);
949 // Now that we have the type info, save it
950 // in the Hashtable if we don't already have an
951 // entry for this SQL type.
953 m_aTypeInfo
.push_back(aInfo
);
956 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
959 // Close the result set/statement.
961 Reference
< XCloseable
> xClose(xRs
,UNO_QUERY
);
964 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
968 void Connection::disposing()
970 MutexGuard
aGuard(m_aMutex
);
974 m_xMetaData
= css::uno::WeakReference
< css::sdbc::XDatabaseMetaData
>();
976 ISC_STATUS_ARRAY status
; /* status vector */
977 if (m_aTransactionHandle
)
979 // TODO: confirm whether we need to ask the user here.
980 isc_rollback_transaction(status
, &m_aTransactionHandle
);
985 if (isc_detach_database(status
, &m_aDBHandle
))
987 evaluateStatusVector(status
, "isc_detach_database", *this);
990 // TODO: write to storage again?
993 cppu::WeakComponentImplHelperBase::disposing();
996 if (m_pDatabaseFileDir
)
998 ::utl::removeTree((m_pDatabaseFileDir
)->GetURL());
999 m_pDatabaseFileDir
.reset();
1003 void Connection::disposeStatements()
1005 MutexGuard
aGuard(m_aMutex
);
1006 for (OWeakRefArray::iterator i
= m_aStatements
.begin(); m_aStatements
.end() != i
; ++i
)
1008 Reference
< XComponent
> xComp(i
->get(), UNO_QUERY
);
1012 m_aStatements
.clear();
1015 uno::Reference
< XTablesSupplier
> Connection::createCatalog()
1017 MutexGuard
aGuard(m_aMutex
);
1019 // m_xCatalog is a weak reference. Reuse it if it still exists.
1020 Reference
< XTablesSupplier
> xCatalog
= m_xCatalog
;
1027 xCatalog
= new Catalog(this);
1028 m_xCatalog
= xCatalog
;