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 OUString
our_sFDBLocation( u
"firebird.fdb"_ustr
);
77 * Older version of LO may store the database in a .fdb file
79 constexpr OUString
our_sFBKLocation( u
"firebird.fbk"_ustr
);
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
)
236 userName
= "sysdba"_ostr
;
237 userPassword
= "masterkey"_ostr
;
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 //----- XServiceInfo ---------------------------------------------------------
343 IMPLEMENT_SERVICE_INFO(Connection
, u
"com.sun.star.sdbc.drivers.firebird.Connection"_ustr
,
344 u
"com.sun.star.sdbc.Connection"_ustr
)
346 Reference
< XBlob
> Connection::createBlob(ISC_QUAD
const * pBlobId
)
348 MutexGuard
aGuard(m_aMutex
);
349 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
351 Reference
< XBlob
> xReturn
= new Blob(&m_aDBHandle
,
352 &m_aTransactionHandle
,
355 m_aStatements
.emplace_back(xReturn
);
359 Reference
< XClob
> Connection::createClob(ISC_QUAD
const * pBlobId
)
361 MutexGuard
aGuard(m_aMutex
);
362 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
364 Reference
< XClob
> xReturn
= new Clob(&m_aDBHandle
,
365 &m_aTransactionHandle
,
368 m_aStatements
.emplace_back(xReturn
);
372 //----- XUnoTunnel ----------------------------------------------------------
374 sal_Int64 SAL_CALL
Connection::getSomething(const css::uno::Sequence
<sal_Int8
>& rId
)
376 return comphelper::getSomethingImpl(rId
, this);
380 const css::uno::Sequence
<sal_Int8
> & Connection::getUnoTunnelId()
382 static const comphelper::UnoIdInit implId
;
383 return implId
.getSeq();
386 //----- XConnection ----------------------------------------------------------
387 Reference
< XStatement
> SAL_CALL
Connection::createStatement( )
389 MutexGuard
aGuard( m_aMutex
);
390 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
393 if(m_aTypeInfo
.empty())
396 // create a statement
397 // the statement can only be executed once
398 Reference
< XStatement
> xReturn
= new OStatement(this);
399 m_aStatements
.emplace_back(xReturn
);
403 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareStatement(
404 const OUString
& _sSql
)
406 SAL_INFO("connectivity.firebird", "prepareStatement() "
407 "called with sql: " << _sSql
);
408 MutexGuard
aGuard(m_aMutex
);
409 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
411 if(m_aTypeInfo
.empty())
414 Reference
< XPreparedStatement
> xReturn
= new OPreparedStatement(this, _sSql
);
415 m_aStatements
.emplace_back(xReturn
);
420 Reference
< XPreparedStatement
> SAL_CALL
Connection::prepareCall(
421 const OUString
& _sSql
)
423 SAL_INFO("connectivity.firebird", "prepareCall(). "
426 MutexGuard
aGuard( m_aMutex
);
427 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
429 // OUString sSqlStatement (transformPreparedStatement( _sSql ));
431 // not implemented yet :-) a task to do
435 OUString SAL_CALL
Connection::nativeSQL( const OUString
& _sSql
)
437 // We do not need to adapt the SQL for Firebird atm.
441 void SAL_CALL
Connection::setAutoCommit( sal_Bool autoCommit
)
443 MutexGuard
aGuard( m_aMutex
);
444 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
446 m_bIsAutoCommit
= autoCommit
;
448 if (m_aTransactionHandle
)
454 sal_Bool SAL_CALL
Connection::getAutoCommit()
456 MutexGuard
aGuard( m_aMutex
);
457 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
459 return m_bIsAutoCommit
;
462 void Connection::setupTransaction()
464 MutexGuard
aGuard( m_aMutex
);
465 ISC_STATUS status_vector
[20];
467 // TODO: is this sensible? If we have changed parameters then transaction
469 if (m_aTransactionHandle
)
472 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
475 char aTransactionIsolation
= 0;
476 switch (m_aTransactionIsolation
)
478 // TODO: confirm that these are correct.
479 case TransactionIsolation::READ_UNCOMMITTED
:
480 aTransactionIsolation
= isc_tpb_concurrency
;
482 case TransactionIsolation::READ_COMMITTED
:
483 aTransactionIsolation
= isc_tpb_read_committed
;
485 case TransactionIsolation::REPEATABLE_READ
:
486 case TransactionIsolation::SERIALIZABLE
:
487 aTransactionIsolation
= isc_tpb_consistency
;
490 assert( false ); // We must have a valid TransactionIsolation.
493 // You cannot pass an empty tpb parameter so we have to do some pointer
494 // arithmetic to avoid problems. (i.e. aTPB[x] = 0 is invalid)
498 *pTPB
++ = isc_tpb_version3
;
500 *pTPB
++ = isc_tpb_autocommit
;
501 *pTPB
++ = (!m_bIsReadOnly
? isc_tpb_write
: isc_tpb_read
);
502 *pTPB
++ = aTransactionIsolation
;
503 *pTPB
++ = isc_tpb_wait
;
505 isc_start_transaction(status_vector
,
506 &m_aTransactionHandle
,
509 pTPB
- aTPB
, // bytes used in TPB
512 evaluateStatusVector(status_vector
,
513 u
"isc_start_transaction",
517 isc_tr_handle
& Connection::getTransaction()
519 MutexGuard
aGuard( m_aMutex
);
520 if (!m_aTransactionHandle
)
524 return m_aTransactionHandle
;
527 void SAL_CALL
Connection::commit()
529 MutexGuard
aGuard( m_aMutex
);
530 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
532 ISC_STATUS status_vector
[20];
534 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
537 isc_commit_transaction(status_vector
, &m_aTransactionHandle
);
538 evaluateStatusVector(status_vector
,
539 u
"isc_commit_transaction",
544 void Connection::loadDatabaseFile(const OUString
& srcLocation
, const OUString
& tmpLocation
)
546 Reference
< XStream
> xDBStream(m_xEmbeddedStorage
->openStreamElement(srcLocation
,
547 ElementModes::READ
));
549 uno::Reference
< ucb::XSimpleFileAccess2
> xFileAccess
=
550 ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() );
551 if ( !xFileAccess
.is() )
553 ::connectivity::SharedResources aResources
;
554 // TODO FIXME: this does _not_ look like the right error message
555 const OUString sMessage
= aResources
.getResourceString(STR_ERROR_NEW_VERSION
);
556 ::dbtools::throwGenericSQLException(sMessage
,*this);
558 xFileAccess
->writeFile(tmpLocation
,xDBStream
->getInputStream());
561 isc_svc_handle
Connection::attachServiceManager()
563 ISC_STATUS_ARRAY aStatusVector
;
564 #if SAL_TYPES_SIZEOFPOINTER == 8
565 isc_svc_handle aServiceHandle
= 0;
567 isc_svc_handle aServiceHandle
= nullptr;
570 char aSPBBuffer
[256];
571 char* pSPB
= aSPBBuffer
;
572 *pSPB
++ = isc_spb_version
;
573 *pSPB
++ = isc_spb_current_version
;
574 *pSPB
++ = isc_spb_user_name
;
575 OUString
sUserName(u
"SYSDBA"_ustr
);
576 char aLength
= static_cast<char>(sUserName
.getLength());
579 OUStringToOString(sUserName
,
580 RTL_TEXTENCODING_UTF8
).getStr(),
583 // TODO: do we need ", isc_dpb_trusted_auth, 1, 1" -- probably not but ...
584 if (isc_service_attach(aStatusVector
,
585 0, // Denotes null-terminated string next
591 evaluateStatusVector(aStatusVector
,
592 u
"isc_service_attach",
596 return aServiceHandle
;
599 void Connection::detachServiceManager(isc_svc_handle aServiceHandle
)
601 ISC_STATUS_ARRAY aStatusVector
;
602 if (isc_service_detach(aStatusVector
,
605 evaluateStatusVector(aStatusVector
,
606 u
"isc_service_detach",
611 void Connection::runBackupService(const short nAction
)
613 assert(nAction
== isc_action_svc_backup
614 || nAction
== isc_action_svc_restore
);
616 ISC_STATUS_ARRAY aStatusVector
;
618 // convert paths to 8-Bit strings
619 OString sFDBPath
= OUStringToOString(m_sFirebirdURL
, RTL_TEXTENCODING_UTF8
);
620 OString sFBKPath
= OUStringToOString(m_sFBKPath
, RTL_TEXTENCODING_UTF8
);
623 sal_uInt16 nFDBLength
= sFDBPath
.getLength();
624 sal_uInt16 nFBKLength
= sFBKPath
.getLength();
625 OStringBuffer
aRequest( // byte array
626 OStringChar(static_cast<char>(nAction
))
627 + OStringChar(char(isc_spb_dbname
)) // .fdb
628 + OStringChar(static_cast<char>(nFDBLength
& 0xFF)) // least significant byte first
629 + OStringChar(static_cast<char>((nFDBLength
>> 8) & 0xFF))
631 + OStringChar(char(isc_spb_bkp_file
)) // .fbk
632 + OStringChar(static_cast<char>(nFBKLength
& 0xFF))
633 + OStringChar(static_cast<char>((nFBKLength
>> 8) & 0xFF))
636 if (nAction
== isc_action_svc_restore
)
638 aRequest
.append(char(isc_spb_options
)); // 4-Byte bitmask
640 char * pOptions
= sOptions
;
642 #pragma warning(push)
643 #pragma warning(disable: 4310) // cast truncates data
645 ADD_SPB_NUMERIC(pOptions
, isc_spb_res_create
);
649 aRequest
.append(sOptions
, 4);
652 isc_svc_handle aServiceHandle
;
653 aServiceHandle
= attachServiceManager();
655 if (isc_service_start(aStatusVector
,
658 aRequest
.getLength(),
661 evaluateStatusVector(aStatusVector
, u
"isc_service_start", *this);
664 char aInfoSPB
= isc_info_svc_line
;
667 // query blocks until success or error
668 if(isc_service_query(aStatusVector
,
670 nullptr, // Reserved null
671 0,nullptr, // "send" spb -- size and spb -- not needed?
677 evaluateStatusVector(aStatusVector
, u
"isc_service_query", *this);
680 detachServiceManager(aServiceHandle
);
684 void SAL_CALL
Connection::rollback()
686 MutexGuard
aGuard( m_aMutex
);
687 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
689 ISC_STATUS status_vector
[20];
691 if (!m_bIsAutoCommit
&& m_aTransactionHandle
)
693 isc_rollback_transaction(status_vector
, &m_aTransactionHandle
);
697 sal_Bool SAL_CALL
Connection::isClosed( )
699 MutexGuard
aGuard( m_aMutex
);
701 // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
702 return Connection_BASE::rBHelper
.bDisposed
;
705 Reference
< XDatabaseMetaData
> SAL_CALL
Connection::getMetaData( )
707 MutexGuard
aGuard( m_aMutex
);
708 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
710 // here we have to create the class with biggest interface
711 // The answer is 42 :-)
712 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
715 xMetaData
= new ODatabaseMetaData(this); // need the connection because it can return it
716 m_xMetaData
= xMetaData
;
722 void SAL_CALL
Connection::setReadOnly(sal_Bool readOnly
)
724 MutexGuard
aGuard( m_aMutex
);
725 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
727 m_bIsReadOnly
= readOnly
;
731 sal_Bool SAL_CALL
Connection::isReadOnly()
733 MutexGuard
aGuard( m_aMutex
);
734 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
736 return m_bIsReadOnly
;
739 void SAL_CALL
Connection::setCatalog(const OUString
& /*catalog*/)
741 ::dbtools::throwFunctionNotSupportedSQLException(u
"setCatalog"_ustr
, *this);
744 OUString SAL_CALL
Connection::getCatalog()
746 ::dbtools::throwFunctionNotSupportedSQLException(u
"getCatalog"_ustr
, *this);
749 void SAL_CALL
Connection::setTransactionIsolation( sal_Int32 level
)
751 MutexGuard
aGuard( m_aMutex
);
752 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
754 m_aTransactionIsolation
= level
;
758 sal_Int32 SAL_CALL
Connection::getTransactionIsolation( )
760 MutexGuard
aGuard( m_aMutex
);
761 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
763 return m_aTransactionIsolation
;
766 Reference
< XNameAccess
> SAL_CALL
Connection::getTypeMap()
768 ::dbtools::throwFeatureNotImplementedSQLException( u
"XConnection::getTypeMap"_ustr
, *this );
771 void SAL_CALL
Connection::setTypeMap(const Reference
< XNameAccess
>&)
773 ::dbtools::throwFeatureNotImplementedSQLException( u
"XConnection::setTypeMap"_ustr
, *this );
776 //----- XCloseable -----------------------------------------------------------
777 void SAL_CALL
Connection::close( )
779 // we just dispose us
781 MutexGuard
aGuard( m_aMutex
);
782 checkDisposed(Connection_BASE::rBHelper
.bDisposed
);
789 Any SAL_CALL
Connection::getWarnings( )
791 // when you collected some warnings -> return it
795 void SAL_CALL
Connection::clearWarnings( )
797 // you should clear your collected warnings here
800 // XDocumentEventListener
801 void SAL_CALL
Connection::documentEventOccured( const DocumentEvent
& Event
)
803 MutexGuard
aGuard(m_aMutex
);
808 if (Event
.EventName
!= "OnSave" && Event
.EventName
!= "OnSaveAs")
811 commit(); // Commit and close transaction
812 if ( !(m_bIsEmbedded
&& m_xEmbeddedStorage
.is()) )
819 void SAL_CALL
Connection::disposing(const EventObject
& /*rSource*/)
821 MutexGuard
aGuard( m_aMutex
);
823 m_xEmbeddedStorage
.clear();
826 void Connection::buildTypeInfo()
828 MutexGuard
aGuard( m_aMutex
);
830 Reference
< XResultSet
> xRs
= getMetaData ()->getTypeInfo ();
831 Reference
< XRow
> xRow(xRs
,UNO_QUERY
);
832 // Information for a single SQL type
834 // Loop on the result set until we reach end of file
839 aInfo
.aTypeName
= xRow
->getString (1);
840 aInfo
.nType
= xRow
->getShort (2);
841 aInfo
.nPrecision
= xRow
->getInt (3);
842 // aLiteralPrefix = xRow->getString (4);
843 // aLiteralSuffix = xRow->getString (5);
844 // aCreateParams = xRow->getString (6);
845 // bNullable = xRow->getBoolean (7);
846 // bCaseSensitive = xRow->getBoolean (8);
847 // nSearchType = xRow->getShort (9);
848 // bUnsigned = xRow->getBoolean (10);
849 // bCurrency = xRow->getBoolean (11);
850 // bAutoIncrement = xRow->getBoolean (12);
851 aInfo
.aLocalTypeName
= xRow
->getString (13);
852 // nMinimumScale = xRow->getShort (14);
853 aInfo
.nMaximumScale
= xRow
->getShort (15);
854 // nNumPrecRadix = (sal_Int16)xRow->getInt(18);
857 // Now that we have the type info, save it
858 // in the Hashtable if we don't already have an
859 // entry for this SQL type.
861 m_aTypeInfo
.push_back(aInfo
);
864 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
867 // Close the result set/statement.
869 Reference
< XCloseable
> xClose(xRs
,UNO_QUERY
);
872 SAL_INFO("connectivity.firebird", "buildTypeInfo(). "
876 void Connection::disposing()
878 MutexGuard
aGuard(m_aMutex
);
882 m_xMetaData
= css::uno::WeakReference
< css::sdbc::XDatabaseMetaData
>();
884 ISC_STATUS_ARRAY status
; /* status vector */
885 if (m_aTransactionHandle
)
887 // TODO: confirm whether we need to ask the user here.
888 isc_rollback_transaction(status
, &m_aTransactionHandle
);
893 if (isc_detach_database(status
, &m_aDBHandle
))
895 evaluateStatusVector(status
, u
"isc_detach_database", *this);
901 cppu::WeakComponentImplHelperBase::disposing();
903 m_pDatabaseFileDir
.reset();
906 void Connection::storeDatabase()
908 MutexGuard
aGuard(m_aMutex
);
909 if (m_bIsEmbedded
&& m_xEmbeddedStorage
.is())
911 SAL_INFO("connectivity.firebird", "Writing .fbk from running db");
914 runBackupService(isc_action_svc_backup
);
916 catch (const SQLException
& e
)
918 auto a
= cppu::getCaughtException();
919 throw WrappedTargetRuntimeException(e
.Message
, e
.Context
, a
);
921 Reference
<XStream
> xDBStream(
922 m_xEmbeddedStorage
->openStreamElement(our_sFBKLocation
, ElementModes::WRITE
));
923 using namespace ::comphelper
;
924 const Reference
<XComponentContext
>& xContext
= comphelper::getProcessComponentContext();
925 Reference
<XInputStream
> xInputStream
;
928 xInputStream
= OStorageHelper::GetInputStreamFromURL(m_sFBKPath
, xContext
);
929 if (xInputStream
.is())
930 OStorageHelper::CopyInputToOutput(xInputStream
, xDBStream
->getOutputStream());
935 void Connection::disposeStatements()
937 MutexGuard
aGuard(m_aMutex
);
938 for (auto const& statement
: m_aStatements
)
940 Reference
< XComponent
> xComp(statement
.get(), UNO_QUERY
);
944 m_aStatements
.clear();
947 uno::Reference
< XTablesSupplier
> Connection::createCatalog()
949 MutexGuard
aGuard(m_aMutex
);
951 // m_xCatalog is a weak reference. Reuse it if it still exists.
952 Reference
< XTablesSupplier
> xCatalog
= m_xCatalog
;
959 xCatalog
= new Catalog(this);
960 m_xCatalog
= xCatalog
;
966 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */