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>
51#include <osl/file.hxx>
52#include <rtl/strbuf.hxx>
81Connection::Connection()
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)
108struct ConnectionGuard
111 explicit ConnectionGuard(oslInterlockedCount& refCount)
114 osl_atomic_increment(&m_refCount);
118 osl_atomic_decrement(&m_refCount);
132 bool bIsNewDatabase =
false;
135 bool bIsFdbStored =
false;
136 if (url ==
"sdbc:embedded:firebird")
140 const PropertyValue* pIter = info.getConstArray();
141 const PropertyValue* pEnd = pIter + info.getLength();
143 for (;pIter != pEnd; ++pIter)
145 if ( pIter->Name ==
"Storage" )
149 else if ( pIter->Name ==
"Document" )
176 SAL_INFO(
"connectivity.firebird",
"Extracting* .fbk from .odb" );
182 SAL_INFO(
"connectivity.firebird",
"Found .fdb instead of .fbk");
190 bIsNewDatabase =
true;
197 else if (url.startsWith(
"sdbc:firebird:"))
203 uno::Reference< ucb::XSimpleFileAccess > xFileAccess =
206 bIsNewDatabase =
true;
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);
220 dpbBuffer.push_back(SQL_DIALECT_CURRENT);
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);
228 dpbBuffer.push_back(isc_dpb_lc_ctype);
229 dpbBuffer.push_back(
sizeof(sCharset) - 1);
230 dpbBuffer.append(sCharset);
237 userPassword =
"masterkey";
241 for (
const auto& rIter : info)
243 if (rIter.Name ==
"user")
248 else if (rIter.Name ==
"password")
256 if (!userName.isEmpty())
258 const sal_Int32 nMaxUsername = 255;
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;
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);
276 dpbBuffer.push_back(isc_dpb_utf8_filename);
277 dpbBuffer.push_back(0);
279 ISC_STATUS_ARRAY status;
284 aErr = isc_create_database(status,
285 sFirebirdURL.getLength(),
286 sFirebirdURL.getStr(),
303 aErr = isc_attach_database(status,
304 sFirebirdURL.getLength(),
305 sFirebirdURL.getStr(),
319 uno::Reference<XDocumentEventBroadcaster> xBroadcaster(
m_xParentDocument, UNO_QUERY);
321 if (xBroadcaster.is())
322 xBroadcaster->addDocumentEventListener(
this);
331 catch (
const std::exception&)
338 throw std::runtime_error(
"Generic Firebird::Exception");
345 "com.sun.star.sdbc.Connection")
347Reference< XBlob>
Connection::createBlob(ISC_QUAD const * pBlobId)
352 Reference< XBlob > xReturn =
new Blob(&m_aDBHandle,
353 &m_aTransactionHandle,
356 m_aStatements.push_back(WeakReferenceHelper(xReturn));
399 Reference< XStatement > xReturn =
new OStatement(
this);
405 const OUString& _sSql)
407 SAL_INFO(
"connectivity.firebird",
"prepareStatement() "
408 "called with sql: " << _sSql);
422 const OUString& _sSql )
424 SAL_INFO(
"connectivity.firebird",
"prepareCall(). "
466 ISC_STATUS status_vector[20];
476 char aTransactionIsolation = 0;
480 case TransactionIsolation::READ_UNCOMMITTED:
481 aTransactionIsolation = isc_tpb_concurrency;
483 case TransactionIsolation::READ_COMMITTED:
484 aTransactionIsolation = isc_tpb_read_committed;
486 case TransactionIsolation::REPEATABLE_READ:
487 aTransactionIsolation = isc_tpb_consistency;
489 case TransactionIsolation::SERIALIZABLE:
490 aTransactionIsolation = isc_tpb_consistency;
501 *pTPB++ = isc_tpb_version3;
503 *pTPB++ = isc_tpb_autocommit;
505 *pTPB++ = aTransactionIsolation;
506 *pTPB++ = isc_tpb_wait;
508 isc_start_transaction(status_vector,
516 u"isc_start_transaction",
535 ISC_STATUS status_vector[20];
542 u"isc_commit_transaction",
550 ElementModes::READ));
552 uno::Reference< ucb::XSimpleFileAccess2 > xFileAccess =
554 if ( !xFileAccess.is() )
561 xFileAccess->writeFile(tmpLocation,xDBStream->getInputStream());
566 ISC_STATUS_ARRAY aStatusVector;
567#if SAL_TYPES_SIZEOFPOINTER == 8
568 isc_svc_handle aServiceHandle = 0;
570 isc_svc_handle aServiceHandle =
nullptr;
573 char aSPBBuffer[256];
574 char* pSPB = aSPBBuffer;
575 *pSPB++ = isc_spb_version;
576 *pSPB++ = isc_spb_current_version;
577 *pSPB++ = isc_spb_user_name;
578 OUString sUserName(
"SYSDBA");
579 char aLength =
static_cast<char>(sUserName.getLength());
583 RTL_TEXTENCODING_UTF8).getStr(),
587 if (isc_service_attach(aStatusVector,
595 u"isc_service_attach",
599 return aServiceHandle;
604 ISC_STATUS_ARRAY aStatusVector;
605 if (isc_service_detach(aStatusVector,
609 u"isc_service_detach",
616 assert(nAction == isc_action_svc_backup
617 || nAction == isc_action_svc_restore);
619 ISC_STATUS_ARRAY aStatusVector;
626 sal_uInt16 nFDBLength = sFDBPath.getLength();
627 sal_uInt16 nFBKLength = sFBKPath.getLength();
628 OStringBuffer aRequest(
629 OStringChar(
static_cast<char>(nAction))
630 + OStringChar(
char(isc_spb_dbname))
631 + OStringChar(
static_cast<char>(nFDBLength & 0xFF))
632 + OStringChar(
static_cast<char>((nFDBLength >> 8) & 0xFF))
634 + OStringChar(
char(isc_spb_bkp_file))
635 + OStringChar(
static_cast<char>(nFBKLength & 0xFF))
636 + OStringChar(
static_cast<char>((nFBKLength >> 8) & 0xFF))
639 if (nAction == isc_action_svc_restore)
641 aRequest.append(
char(isc_spb_options));
643 char * pOptions = sOptions;
646#pragma warning(disable: 4310)
648 ADD_SPB_NUMERIC(pOptions, isc_spb_res_create);
652 aRequest.append(sOptions, 4);
655 isc_svc_handle aServiceHandle;
658 if (isc_service_start(aStatusVector,
661 aRequest.getLength(),
667 char aInfoSPB = isc_info_svc_line;
671 if(isc_service_query(aStatusVector,
692 ISC_STATUS status_vector[20];
705 return Connection_BASE::rBHelper.bDisposed;
715 Reference< XDatabaseMetaData > xMetaData =
m_xMetaData;
813 if (Event.EventName !=
"OnSave" && Event.EventName !=
"OnSaveAs")
834 Reference< XResultSet> xRs =
getMetaData ()->getTypeInfo ();
835 Reference< XRow> xRow(xRs,UNO_QUERY);
844 aInfo.
nType = xRow->getShort (2);
868 SAL_INFO(
"connectivity.firebird",
"buildTypeInfo(). "
873 Reference< XCloseable> xClose(xRs,UNO_QUERY);
876 SAL_INFO(
"connectivity.firebird",
"buildTypeInfo(). "
886 m_xMetaData = css::uno::WeakReference< css::sdbc::XDatabaseMetaData>();
888 ISC_STATUS_ARRAY status;
905 cppu::WeakComponentImplHelperBase::disposing();
916 SAL_INFO(
"connectivity.firebird",
"Writing .fbk from running db");
921 catch (
const SQLException& e)
924 throw WrappedTargetRuntimeException(e.Message, e.Context,
a);
927 Reference<XStream> xDBStream(
932 Reference<XInputStream> xInputStream;
937 if (xInputStream.is())
941 uno::Reference<ucb::XSimpleFileAccess> xFileAccess
942 = ucb::SimpleFileAccess::create(xContext);
949 cppu::WeakComponentImplHelperBase::disposing();
960 Reference< XComponent > xComp(statement.get(), UNO_QUERY);
972 Reference< XTablesSupplier > xCatalog =
m_xCatalog;
constexpr OUStringLiteral our_sFBKLocation(u"firebird.fbk")
Older version of LO may store the database in a .fdb file.
IMPLEMENT_SERVICE_INFO(Connection, "com.sun.star.sdbc.drivers.firebird.Connection", "com.sun.star.sdbc.Connection") Reference< XBlob > Connection
constexpr OUStringLiteral our_sFDBLocation(u"firebird.fdb")
Location within the .odb that an embedded .fdb will be stored.
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
static css::uno::Reference< css::io::XInputStream > GetInputStreamFromURL(const OUString &aURL, const css::uno::Reference< css::uno::XComponentContext > &context)
const css::uno::Sequence< sal_Int8 > & getSeq() const
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
virtual void SAL_CALL setReadOnly(sal_Bool readOnly) override
void storeDatabase()
Backup and store embedded extracted database to the .odb file.
css::uno::Reference< css::sdbcx::XTablesSupplier > createCatalog()
Create and/or connect to the sdbcx Catalog.
virtual css::uno::Any SAL_CALL getWarnings() override
css::uno::WeakReference< css::sdbc::XDatabaseMetaData > m_xMetaData
virtual sal_Bool SAL_CALL getAutoCommit() override
virtual sal_Bool SAL_CALL isReadOnly() override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL setTypeMap(const css::uno::Reference< css::container::XNameAccess > &typeMap) override
void setupTransaction()
Creates a new transaction with the desired parameters, if necessary discarding an existing transactio...
css::uno::Reference< css::sdbc::XClob > createClob(ISC_QUAD const *pBlobID)
void loadDatabaseFile(const OUString &pSrcLocation, const OUString &pTmpLocation)
css::uno::WeakReference< css::sdbcx::XTablesSupplier > m_xCatalog
virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement(const OUString &sql) override
virtual sal_Int32 SAL_CALL getTransactionIsolation() override
TTypeInfoVector m_aTypeInfo
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap() override
bool m_bIsFile
We are using an external (local) file.
virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 > &rId) override
virtual void SAL_CALL setTransactionIsolation(sal_Int32 level) override
virtual void SAL_CALL documentEventOccured(const css::document::DocumentEvent &Event) override
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
virtual void SAL_CALL clearWarnings() override
OWeakRefArray m_aStatements
Statements owned by this connection.
virtual void SAL_CALL setCatalog(const OUString &catalog) override
virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData() override
virtual sal_Bool SAL_CALL isClosed() override
virtual ~Connection() override
void runBackupService(const short nAction)
Run the backup service, use nAction = isc_action_svc_backup to backup, nAction = isc_action_svc_resto...
virtual OUString SAL_CALL getCatalog() override
bool m_bIsEmbedded
Denotes that we have a database stored within a .odb file.
void detachServiceManager(isc_svc_handle pServiceHandle)
OUString m_sFBKPath
Path for our extracted .fbk file.
isc_svc_handle attachServiceManager()
virtual void SAL_CALL setAutoCommit(sal_Bool autoCommit) override
void construct(const OUString &url, const css::uno::Sequence< css::beans::PropertyValue > &info)
isc_tr_handle & getTransaction()
virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall(const OUString &sql) override
virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement() override
std::unique_ptr< ::utl::TempFileNamed > m_pDatabaseFileDir
The temporary folder where we extract the .fbk from a .odb, and also store the temporary ....
isc_tr_handle m_aTransactionHandle
virtual void SAL_CALL close() override
virtual void SAL_CALL rollback() override
css::uno::Reference< css::embed::XStorage > m_xEmbeddedStorage
Handle for the folder within the .odb where we store our .fbk (Only used if m_bIsEmbedded is true).
OUString m_sConnectionURL
The URL passed to us when opening, i.e.
sal_Int32 m_aTransactionIsolation
virtual OUString SAL_CALL nativeSQL(const OUString &sql) override
virtual void SAL_CALL commit() override
OUString m_sFirebirdURL
The URL passed to firebird, i.e.
css::uno::Reference< css::util::XModifiable > m_xParentDocument
Handle for the parent DatabaseDocument.
isc_db_handle m_aDBHandle
#define SAL_INFO(area, stream)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
sal_Int64 getSomethingImpl(const css::uno::Sequence< sal_Int8 > &rId, T *pThis, FallbackToGetSomethingOf< Base >={})
Reference< XComponentContext > getProcessComponentContext()
void checkDisposed(bool _bThrow)
void evaluateStatusVector(const ISC_STATUS_ARRAY &rStatusVector, std::u16string_view aCause, const css::uno::Reference< css::uno::XInterface > &_rxContext)
Evaluate a firebird status vector and throw exceptions as necessary.
::cppu::WeakComponentImplHelper< css::document::XDocumentEventListener, css::lang::XServiceInfo, css::lang::XUnoTunnel, css::sdbc::XConnection, css::sdbc::XWarningsSupplier > Connection_BASE
Any SAL_CALL getCaughtException()
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)