1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 .
21 #include "Catalog.hxx"
23 #include "Connection.hxx"
24 #include "DatabaseMetaData.hxx"
25 #include "PreparedStatement.hxx"
26 #include "Statement.hxx"
31 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
32 #include <com/sun/star/embed/ElementModes.hpp>
33 #include <com/sun/star/io/XStream.hpp>
34 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
35 #include <com/sun/star/sdbc/SQLException.hpp>
36 #include <com/sun/star/sdbc/XRow.hpp>
37 #include <com/sun/star/sdbc/TransactionIsolation.hpp>
38 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
39 #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
41 #include <connectivity/dbexception.hxx>
42 #include <strings.hrc>
43 #include <resource/sharedresources.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/servicehelper.hxx>
47 #include <comphelper/storagehelper.hxx>
48 #include <cppuhelper/exc_hlp.hxx>
49 #include <unotools/tempfile.hxx>
51 #include <osl/file.hxx>
52 #include <rtl/strbuf.hxx>
53 #include <sal/log.hxx>
55 using namespace connectivity::firebird
;
56 using namespace connectivity
;
58 using namespace ::osl
;
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::beans
;
62 using namespace ::com::sun::star::container
;
63 using namespace ::com::sun::star::document
;
64 using namespace ::com::sun::star::embed
;
65 using namespace ::com::sun::star::io
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::sdbc
;
68 using namespace ::com::sun::star::sdbcx
;
69 using namespace ::com::sun::star::uno
;
72 * Location within the .odb that an embedded .fdb will be stored.
73 * Only relevant for embedded dbs.
75 constexpr OUStringLiteral
our_sFDBLocation( u
"firebird.fdb" );
77 * Older version of LO may store the database in a .fdb file
79 constexpr OUStringLiteral
our_sFBKLocation( u
"firebird.fbk" );
81 Connection::Connection()
82 : Connection_BASE(m_aMutex
)
83 , m_bIsEmbedded(false)
85 , m_bIsAutoCommit(true)
86 , m_bIsReadOnly(false)
87 , m_aTransactionIsolation(TransactionIsolation::REPEATABLE_READ
)
88 #if SAL_TYPES_SIZEOFPOINTER == 8
90 , m_aTransactionHandle(0)
92 , m_aDBHandle(nullptr)
93 , m_aTransactionHandle(nullptr)
96 , m_xMetaData(nullptr)
100 Connection::~Connection()
108 struct ConnectionGuard
110 oslInterlockedCount
& m_refCount
;
111 explicit ConnectionGuard(oslInterlockedCount
& refCount
)
112 : m_refCount(refCount
)
114 osl_atomic_increment(&m_refCount
);
118 osl_atomic_decrement(&m_refCount
);
124 void Connection::construct(const OUString
& url
, const Sequence
< PropertyValue
>& info
)
126 ConnectionGuard
aGuard(m_refCount
);
130 m_sConnectionURL
= url
;
132 bool bIsNewDatabase
= false;
133 // the database may be stored as an
134 // fdb file in older versions
135 bool bIsFdbStored
= false;
136 if (url
== "sdbc:embedded:firebird")
138 m_bIsEmbedded
= true;
140 const PropertyValue
* pIter
= info
.getConstArray();
141 const PropertyValue
* pEnd
= pIter
+ info
.getLength();
143 for (;pIter
!= pEnd
; ++pIter
)
145 if ( pIter
->Name
== "Storage" )
147 m_xEmbeddedStorage
.set(pIter
->Value
,UNO_QUERY
);
149 else if ( pIter
->Name
== "Document" )
151 pIter
->Value
>>= m_xParentDocument
;
155 if ( !m_xEmbeddedStorage
.is() )
157 ::connectivity::SharedResources aResources
;
158 const OUString sMessage
= aResources
.getResourceString(STR_NO_STORAGE
);
159 ::dbtools::throwGenericSQLException(sMessage
,*this);
162 bIsNewDatabase
= !m_xEmbeddedStorage
->hasElements();
164 m_pDatabaseFileDir
.reset(new ::utl::TempFileNamed(nullptr, true));
165 m_pDatabaseFileDir
->EnableKillingFile();
166 m_sFirebirdURL
= m_pDatabaseFileDir
->GetFileName() + "/firebird.fdb";
167 m_sFBKPath
= m_pDatabaseFileDir
->GetFileName() + "/firebird.fbk";
169 SAL_INFO("connectivity.firebird", "Temporary .fdb location: " << m_sFirebirdURL
);
173 if (m_xEmbeddedStorage
->hasByName(our_sFBKLocation
) &&
174 m_xEmbeddedStorage
->isStreamElement(our_sFBKLocation
))
176 SAL_INFO("connectivity.firebird", "Extracting* .fbk from .odb" );
177 loadDatabaseFile(our_sFBKLocation
, m_sFBKPath
);
179 else if(m_xEmbeddedStorage
->hasByName(our_sFDBLocation
) &&
180 m_xEmbeddedStorage
->isStreamElement(our_sFDBLocation
))
182 SAL_INFO("connectivity.firebird", "Found .fdb instead of .fbk");
184 loadDatabaseFile(our_sFDBLocation
, m_sFirebirdURL
);
188 // There might be files which are not firebird databases.
189 // This is not a problem.
190 bIsNewDatabase
= true;
193 // TODO: Get DB properties from XML
196 // External file AND/OR remote connection
197 else if (url
.startsWith("sdbc:firebird:"))
199 m_sFirebirdURL
= url
.copy(strlen("sdbc:firebird:"));
200 if (m_sFirebirdURL
.startsWith("file://"))
203 uno::Reference
< ucb::XSimpleFileAccess
> xFileAccess
=
204 ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext());
205 if (!xFileAccess
->exists(m_sFirebirdURL
))
206 bIsNewDatabase
= true;
208 osl::FileBase::getSystemPathFromFileURL(m_sFirebirdURL
, m_sFirebirdURL
);
212 std::string dpbBuffer
;
215 OString userPassword
;
217 dpbBuffer
.push_back(isc_dpb_version1
);
218 dpbBuffer
.push_back(isc_dpb_sql_dialect
);
219 dpbBuffer
.push_back(1); // 1 byte long
220 dpbBuffer
.push_back(SQL_DIALECT_CURRENT
);
222 // set UTF8 as default character set of the database
223 const char sCharset
[] = "UTF8";
224 dpbBuffer
.push_back(isc_dpb_set_db_charset
);
225 dpbBuffer
.push_back(sizeof(sCharset
) - 1);
226 dpbBuffer
.append(sCharset
);
227 // set UTF8 as default character set of the connection
228 dpbBuffer
.push_back(isc_dpb_lc_ctype
);
229 dpbBuffer
.push_back(sizeof(sCharset
) - 1);
230 dpbBuffer
.append(sCharset
);
232 // Do any more dpbBuffer additions here
234 if (m_bIsEmbedded
|| m_bIsFile
)
237 userPassword
= "masterkey";
241 for (const auto& rIter
: info
)
243 if (rIter
.Name
== "user")
245 if (OUString value
; rIter
.Value
>>= value
)
246 userName
= OUStringToOString(value
, RTL_TEXTENCODING_UTF8
);
248 else if (rIter
.Name
== "password")
250 if (OUString value
; rIter
.Value
>>= value
)
251 userPassword
= OUStringToOString(value
, RTL_TEXTENCODING_UTF8
);
256 if (!userName
.isEmpty())
258 const sal_Int32 nMaxUsername
= 255; //max size
259 int nUsernameLength
= std::min(userName
.getLength(), nMaxUsername
);
260 dpbBuffer
.push_back(isc_dpb_user_name
);
261 dpbBuffer
.push_back(nUsernameLength
);
262 dpbBuffer
.append(userName
.getStr(), nUsernameLength
);
265 if (!userPassword
.isEmpty())
267 const sal_Int32 nMaxPassword
= 255; //max size
268 int nPasswordLength
= std::min(userPassword
.getLength(), nMaxPassword
);
269 dpbBuffer
.push_back(isc_dpb_password
);
270 dpbBuffer
.push_back(nPasswordLength
);
271 dpbBuffer
.append(userPassword
.getStr(), nPasswordLength
);
275 // use isc_dpb_utf8_filename to identify encoding of filenames
276 dpbBuffer
.push_back(isc_dpb_utf8_filename
);
277 dpbBuffer
.push_back(0); // no filename here, it is passed to functions directly
279 ISC_STATUS_ARRAY status
; /* status vector */
281 const OString sFirebirdURL
= OUStringToOString(m_sFirebirdURL
, RTL_TEXTENCODING_UTF8
);
284 aErr
= isc_create_database(status
,
285 sFirebirdURL
.getLength(),
286 sFirebirdURL
.getStr(),
293 evaluateStatusVector(status
, u
"isc_create_database", *this);
298 if (m_bIsEmbedded
&& !bIsFdbStored
) // We need to restore the .fbk first
300 runBackupService(isc_action_svc_restore
);
303 aErr
= isc_attach_database(status
,
304 sFirebirdURL
.getLength(),
305 sFirebirdURL
.getStr(),
311 evaluateStatusVector(status
, u
"isc_attach_database", *this);
315 if (m_bIsEmbedded
) // Add DocumentEventListener to save the .fdb as needed
317 // We need to attach as a document listener in order to be able to store
318 // the temporary db back into the .odb when saving
319 uno::Reference
<XDocumentEventBroadcaster
> xBroadcaster(m_xParentDocument
, UNO_QUERY
);
321 if (xBroadcaster
.is())
322 xBroadcaster
->addDocumentEventListener(this);
327 catch (const Exception
&)
331 catch (const std::exception
&)
335 catch (...) // const Firebird::Exception& firebird throws this, but doesn't install the fb_exception.h that declares it
338 throw std::runtime_error("Generic Firebird::Exception");
342 void Connection::notifyDatabaseModified()
344 if (m_xParentDocument
.is()) // Only true in embedded mode
345 m_xParentDocument
->setModified(true);
348 //----- XServiceInfo ---------------------------------------------------------
349 IMPLEMENT_SERVICE_INFO(Connection
, "com.sun.star.sdbc.drivers.firebird.Connection",
350 "com.sun.star.sdbc.Connection")
352 Reference
< XBlob
> Connection::createBlob(ISC_QUAD
const * pBlobId
)
354 MutexGuard
aGuard(m_aMutex
);
355 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
357 Reference
< XBlob
> xReturn
= new Blob(&m_aDBHandle
,
358 &m_aTransactionHandle
,
361 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
365 Reference
< XClob
> Connection::createClob(ISC_QUAD
const * pBlobId
)
367 MutexGuard
aGuard(m_aMutex
);
368 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
370 Reference
< XClob
> xReturn
= new Clob(&m_aDBHandle
,
371 &m_aTransactionHandle
,
374 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
378 //----- XUnoTunnel ----------------------------------------------------------
380 sal_Int64 SAL_CALL
Connection::getSomething(const css::uno::Sequence
<sal_Int8
>& rId
)
382 return comphelper::getSomethingImpl(rId
, this);
386 const css::uno::Sequence
<sal_Int8
> & Connection::getUnoTunnelId()
388 static const comphelper::UnoIdInit implId
;
389 return implId
.getSeq();
392 //----- XConnection ----------------------------------------------------------
393 Reference
< XStatement
> SAL_CALL
Connection::createStatement( )
395 MutexGuard
aGuard( m_aMutex
);
396 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
399 if(m_aTypeInfo
.empty())
402 // create a statement
403 // the statement can only be executed once
404 Reference
< XStatement
> xReturn
= new OStatement(this);
405 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
409 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareStatement(
410 const OUString
& _sSql
)
412 SAL_INFO("connectivity.firebird", "prepareStatement() "
413 "called with sql: " << _sSql
);
414 MutexGuard
aGuard(m_aMutex
);
415 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
417 if(m_aTypeInfo
.empty())
420 Reference
< XPreparedStatement
> xReturn
= new OPreparedStatement(this, _sSql
);
421 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
426 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareCall(
427 const OUString
& _sSql
)
429 SAL_INFO("connectivity.firebird", "prepareCall(). "
432 MutexGuard
aGuard( m_aMutex
);
433 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
435 // OUString sSqlStatement (transformPreparedStatement( _sSql ));
437 // not implemented yet :-) a task to do
441 OUString SAL_CALL
Connection::nativeSQL( const OUString
& _sSql
)
443 // We do not need to adapt the SQL for Firebird atm.
447 void SAL_CALL
Connection::setAutoCommit( sal_Bool autoCommit
)
449 MutexGuard
aGuard( m_aMutex
);
450 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
452 m_bIsAutoCommit
= autoCommit
;
454 if (m_aTransactionHandle
)
460 sal_Bool SAL_CALL
Connection::getAutoCommit()
462 MutexGuard
aGuard( m_aMutex
);
463 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
465 return m_bIsAutoCommit
;
468 void Connection::setupTransaction()
470 MutexGuard
aGuard( m_aMutex
);
471 ISC_STATUS status_vector
[20];
473 // TODO: is this sensible? If we have changed parameters then transaction
475 if (m_aTransactionHandle
)
478 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
481 char aTransactionIsolation
= 0;
482 switch (m_aTransactionIsolation
)
484 // TODO: confirm that these are correct.
485 case TransactionIsolation::READ_UNCOMMITTED
:
486 aTransactionIsolation
= isc_tpb_concurrency
;
488 case TransactionIsolation::READ_COMMITTED
:
489 aTransactionIsolation
= isc_tpb_read_committed
;
491 case TransactionIsolation::REPEATABLE_READ
:
492 aTransactionIsolation
= isc_tpb_consistency
;
494 case TransactionIsolation::SERIALIZABLE
:
495 aTransactionIsolation
= isc_tpb_consistency
;
498 assert( false ); // We must have a valid TransactionIsolation.
501 // You cannot pass an empty tpb parameter so we have to do some pointer
502 // arithmetic to avoid problems. (i.e. aTPB[x] = 0 is invalid)
506 *pTPB
++ = isc_tpb_version3
;
508 *pTPB
++ = isc_tpb_autocommit
;
509 *pTPB
++ = (!m_bIsReadOnly
? isc_tpb_write
: isc_tpb_read
);
510 *pTPB
++ = aTransactionIsolation
;
511 *pTPB
++ = isc_tpb_wait
;
513 isc_start_transaction(status_vector
,
514 &m_aTransactionHandle
,
517 pTPB
- aTPB
, // bytes used in TPB
520 evaluateStatusVector(status_vector
,
521 u
"isc_start_transaction",
525 isc_tr_handle
& Connection::getTransaction()
527 MutexGuard
aGuard( m_aMutex
);
528 if (!m_aTransactionHandle
)
532 return m_aTransactionHandle
;
535 void SAL_CALL
Connection::commit()
537 MutexGuard
aGuard( m_aMutex
);
538 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
540 ISC_STATUS status_vector
[20];
542 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
545 isc_commit_transaction(status_vector
, &m_aTransactionHandle
);
546 evaluateStatusVector(status_vector
,
547 u
"isc_commit_transaction",
552 void Connection::loadDatabaseFile(const OUString
& srcLocation
, const OUString
& tmpLocation
)
554 Reference
< XStream
> xDBStream(m_xEmbeddedStorage
->openStreamElement(srcLocation
,
555 ElementModes::READ
));
557 uno::Reference
< ucb::XSimpleFileAccess2
> xFileAccess
=
558 ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
559 if ( !xFileAccess
.is() )
561 ::connectivity::SharedResources aResources
;
562 // TODO FIXME: this does _not_ look like the right error message
563 const OUString sMessage
= aResources
.getResourceString(STR_ERROR_NEW_VERSION
);
564 ::dbtools::throwGenericSQLException(sMessage
,*this);
566 xFileAccess
->writeFile(tmpLocation
,xDBStream
->getInputStream());
569 isc_svc_handle
Connection::attachServiceManager()
571 ISC_STATUS_ARRAY aStatusVector
;
572 #if SAL_TYPES_SIZEOFPOINTER == 8
573 isc_svc_handle aServiceHandle
= 0;
575 isc_svc_handle aServiceHandle
= nullptr;
578 char aSPBBuffer
[256];
579 char* pSPB
= aSPBBuffer
;
580 *pSPB
++ = isc_spb_version
;
581 *pSPB
++ = isc_spb_current_version
;
582 *pSPB
++ = isc_spb_user_name
;
583 OUString
sUserName("SYSDBA");
584 char aLength
= static_cast<char>(sUserName
.getLength());
587 OUStringToOString(sUserName
,
588 RTL_TEXTENCODING_UTF8
).getStr(),
591 // TODO: do we need ", isc_dpb_trusted_auth, 1, 1" -- probably not but ...
592 if (isc_service_attach(aStatusVector
,
593 0, // Denotes null-terminated string next
599 evaluateStatusVector(aStatusVector
,
600 u
"isc_service_attach",
604 return aServiceHandle
;
607 void Connection::detachServiceManager(isc_svc_handle aServiceHandle
)
609 ISC_STATUS_ARRAY aStatusVector
;
610 if (isc_service_detach(aStatusVector
,
613 evaluateStatusVector(aStatusVector
,
614 u
"isc_service_detach",
619 void Connection::runBackupService(const short nAction
)
621 assert(nAction
== isc_action_svc_backup
622 || nAction
== isc_action_svc_restore
);
624 ISC_STATUS_ARRAY aStatusVector
;
626 // convert paths to 8-Bit strings
627 OString sFDBPath
= OUStringToOString(m_sFirebirdURL
, RTL_TEXTENCODING_UTF8
);
628 OString sFBKPath
= OUStringToOString(m_sFBKPath
, RTL_TEXTENCODING_UTF8
);
631 sal_uInt16 nFDBLength
= sFDBPath
.getLength();
632 sal_uInt16 nFBKLength
= sFBKPath
.getLength();
633 OStringBuffer
aRequest( // byte array
634 OStringChar(static_cast<char>(nAction
))
635 + OStringChar(char(isc_spb_dbname
)) // .fdb
636 + OStringChar(static_cast<char>(nFDBLength
& 0xFF)) // least significant byte first
637 + OStringChar(static_cast<char>((nFDBLength
>> 8) & 0xFF))
639 + OStringChar(char(isc_spb_bkp_file
)) // .fbk
640 + OStringChar(static_cast<char>(nFBKLength
& 0xFF))
641 + OStringChar(static_cast<char>((nFBKLength
>> 8) & 0xFF))
644 if (nAction
== isc_action_svc_restore
)
646 aRequest
.append(char(isc_spb_options
)); // 4-Byte bitmask
648 char * pOptions
= sOptions
;
650 #pragma warning(push)
651 #pragma warning(disable: 4310) // cast truncates data
653 ADD_SPB_NUMERIC(pOptions
, isc_spb_res_create
);
657 aRequest
.append(sOptions
, 4);
660 isc_svc_handle aServiceHandle
;
661 aServiceHandle
= attachServiceManager();
663 if (isc_service_start(aStatusVector
,
666 aRequest
.getLength(),
669 evaluateStatusVector(aStatusVector
, u
"isc_service_start", *this);
672 char aInfoSPB
= isc_info_svc_line
;
675 // query blocks until success or error
676 if(isc_service_query(aStatusVector
,
678 nullptr, // Reserved null
679 0,nullptr, // "send" spb -- size and spb -- not needed?
685 evaluateStatusVector(aStatusVector
, u
"isc_service_query", *this);
688 detachServiceManager(aServiceHandle
);
692 void SAL_CALL
Connection::rollback()
694 MutexGuard
aGuard( m_aMutex
);
695 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
697 ISC_STATUS status_vector
[20];
699 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
701 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
705 sal_Bool SAL_CALL
Connection::isClosed( )
707 MutexGuard
aGuard( m_aMutex
);
709 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
710 return Connection_BASE::rBHelper
.bDisposed
;
713 Reference
< XDatabaseMetaData
> SAL_CALL
Connection::getMetaData( )
715 MutexGuard
aGuard( m_aMutex
);
716 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
718 // here we have to create the class with biggest interface
719 // The answer is 42 :-)
720 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
723 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
724 m_xMetaData
= xMetaData
;
730 void SAL_CALL
Connection::setReadOnly(sal_Bool readOnly
)
732 MutexGuard
aGuard( m_aMutex
);
733 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
735 m_bIsReadOnly
= readOnly
;
739 sal_Bool SAL_CALL
Connection::isReadOnly()
741 MutexGuard
aGuard( m_aMutex
);
742 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
744 return m_bIsReadOnly
;
747 void SAL_CALL
Connection::setCatalog(const OUString
& /*catalog*/)
749 ::dbtools::throwFunctionNotSupportedSQLException("setCatalog", *this);
752 OUString SAL_CALL
Connection::getCatalog()
754 ::dbtools::throwFunctionNotSupportedSQLException("getCatalog", *this);
758 void SAL_CALL
Connection::setTransactionIsolation( sal_Int32 level
)
760 MutexGuard
aGuard( m_aMutex
);
761 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
763 m_aTransactionIsolation
= level
;
767 sal_Int32 SAL_CALL
Connection::getTransactionIsolation( )
769 MutexGuard
aGuard( m_aMutex
);
770 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
772 return m_aTransactionIsolation
;
775 Reference
< XNameAccess
> SAL_CALL
Connection::getTypeMap()
777 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::getTypeMap", *this );
781 void SAL_CALL
Connection::setTypeMap(const Reference
< XNameAccess
>&)
783 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
786 //----- XCloseable -----------------------------------------------------------
787 void SAL_CALL
Connection::close( )
789 // we just dispose us
791 MutexGuard
aGuard( m_aMutex
);
792 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
799 Any SAL_CALL
Connection::getWarnings( )
801 // when you collected some warnings -> return it
805 void SAL_CALL
Connection::clearWarnings( )
807 // you should clear your collected warnings here
810 // XDocumentEventListener
811 void SAL_CALL
Connection::documentEventOccured( const DocumentEvent
& Event
)
813 MutexGuard
aGuard(m_aMutex
);
818 if (Event
.EventName
!= "OnSave" && Event
.EventName
!= "OnSaveAs")
821 commit(); // Commit and close transaction
822 if ( !(m_bIsEmbedded
&& m_xEmbeddedStorage
.is()) )
825 SAL_INFO("connectivity.firebird", "Writing .fbk from running db");
828 runBackupService(isc_action_svc_backup
);
830 catch (const SQLException
& e
)
832 auto a
= cppu::getCaughtException();
833 throw WrappedTargetRuntimeException(e
.Message
, e
.Context
, a
);
837 Reference
< XStream
> xDBStream(m_xEmbeddedStorage
->openStreamElement(our_sFBKLocation
,
838 ElementModes::WRITE
));
840 // TODO: verify the backup actually exists -- the backup service
841 // can fail without giving any sane error messages / telling us
843 using namespace ::comphelper
;
844 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
845 Reference
< XInputStream
> xInputStream
;
850 OStorageHelper::GetInputStreamFromURL(m_sFBKPath
, xContext
);
851 if (xInputStream
.is())
852 OStorageHelper::CopyInputToOutput( xInputStream
,
853 xDBStream
->getOutputStream());
855 // remove old fdb file if exists
856 uno::Reference
< ucb::XSimpleFileAccess
> xFileAccess
=
857 ucb::SimpleFileAccess::create(xContext
);
858 if (xFileAccess
->exists(m_sFirebirdURL
))
859 xFileAccess
->kill(m_sFirebirdURL
);
862 void SAL_CALL
Connection::disposing(const EventObject
& /*rSource*/)
864 MutexGuard
aGuard( m_aMutex
);
866 m_xEmbeddedStorage
.clear();
869 void Connection::buildTypeInfo()
871 MutexGuard
aGuard( m_aMutex
);
873 Reference
< XResultSet
> xRs
= getMetaData ()->getTypeInfo ();
874 Reference
< XRow
> xRow(xRs
,UNO_QUERY
);
875 // Information for a single SQL type
877 // Loop on the result set until we reach end of file
882 aInfo
.aTypeName
= xRow
->getString (1);
883 aInfo
.nType
= xRow
->getShort (2);
884 aInfo
.nPrecision
= xRow
->getInt (3);
885 // aLiteralPrefix = xRow->getString (4);
886 // aLiteralSuffix = xRow->getString (5);
887 // aCreateParams = xRow->getString (6);
888 // bNullable = xRow->getBoolean (7);
889 // bCaseSensitive = xRow->getBoolean (8);
890 // nSearchType = xRow->getShort (9);
891 // bUnsigned = xRow->getBoolean (10);
892 // bCurrency = xRow->getBoolean (11);
893 // bAutoIncrement = xRow->getBoolean (12);
894 aInfo
.aLocalTypeName
= xRow
->getString (13);
895 // nMinimumScale = xRow->getShort (14);
896 aInfo
.nMaximumScale
= xRow
->getShort (15);
897 // nNumPrecRadix = (sal_Int16)xRow->getInt(18);
900 // Now that we have the type info, save it
901 // in the Hashtable if we don't already have an
902 // entry for this SQL type.
904 m_aTypeInfo
.push_back(aInfo
);
907 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
910 // Close the result set/statement.
912 Reference
< XCloseable
> xClose(xRs
,UNO_QUERY
);
915 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
919 void Connection::disposing()
921 MutexGuard
aGuard(m_aMutex
);
925 m_xMetaData
= css::uno::WeakReference
< css::sdbc::XDatabaseMetaData
>();
927 ISC_STATUS_ARRAY status
; /* status vector */
928 if (m_aTransactionHandle
)
930 // TODO: confirm whether we need to ask the user here.
931 isc_rollback_transaction(status
, &m_aTransactionHandle
);
936 if (isc_detach_database(status
, &m_aDBHandle
))
938 evaluateStatusVector(status
, u
"isc_detach_database", *this);
941 // TODO: write to storage again?
943 cppu::WeakComponentImplHelperBase::disposing();
945 m_pDatabaseFileDir
.reset();
948 void Connection::disposeStatements()
950 MutexGuard
aGuard(m_aMutex
);
951 for (auto const& statement
: m_aStatements
)
953 Reference
< XComponent
> xComp(statement
.get(), UNO_QUERY
);
957 m_aStatements
.clear();
960 uno::Reference
< XTablesSupplier
> Connection::createCatalog()
962 MutexGuard
aGuard(m_aMutex
);
964 // m_xCatalog is a weak reference. Reuse it if it still exists.
965 Reference
< XTablesSupplier
> xCatalog
= m_xCatalog
;
972 xCatalog
= new Catalog(this);
973 m_xCatalog
= xCatalog
;
979 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */