/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** * Location within the .odb that an embedded .fdb will be stored. * Only relevant for embedded dbs.
*/
constexpr OUString our_sFDBLocation( u"firebird.fdb"_ustr ); /** * Older version of LO may store the database in a .fdb file
*/
constexpr OUString our_sFBKLocation( u"firebird.fbk"_ustr );
bool bIsNewDatabase = false; // the database may be stored as an // fdb file in older versions bool bIsFdbStored = false; if (url == "sdbc:embedded:firebird")
{
m_bIsEmbedded = true;
const PropertyValue* pIter = info.getConstArray(); const PropertyValue* pEnd = pIter + info.getLength();
if (!bIsNewDatabase)
{ if (m_xEmbeddedStorage->hasByName(our_sFBKLocation) &&
m_xEmbeddedStorage->isStreamElement(our_sFBKLocation))
{
SAL_INFO("connectivity.firebird", "Extracting* .fbk from .odb" );
loadDatabaseFile(our_sFBKLocation, m_sFBKPath);
} elseif(m_xEmbeddedStorage->hasByName(our_sFDBLocation) &&
m_xEmbeddedStorage->isStreamElement(our_sFDBLocation))
{
SAL_INFO("connectivity.firebird", "Found .fdb instead of .fbk");
bIsFdbStored = true;
loadDatabaseFile(our_sFDBLocation, m_sFirebirdURL);
} else
{ // There might be files which are not firebird databases. // This is not a problem.
bIsNewDatabase = true;
}
} // TODO: Get DB properties from XML
dpbBuffer.push_back(isc_dpb_version1);
dpbBuffer.push_back(isc_dpb_sql_dialect);
dpbBuffer.push_back(1); // 1 byte long
dpbBuffer.push_back(SQL_DIALECT_CURRENT);
// set UTF8 as default character set of the database constchar sCharset[] = "UTF8";
dpbBuffer.push_back(isc_dpb_set_db_charset);
dpbBuffer.push_back(sizeof(sCharset) - 1);
dpbBuffer.append(sCharset); // set UTF8 as default character set of the connection
dpbBuffer.push_back(isc_dpb_lc_ctype);
dpbBuffer.push_back(sizeof(sCharset) - 1);
dpbBuffer.append(sCharset);
// use isc_dpb_utf8_filename to identify encoding of filenames
dpbBuffer.push_back(isc_dpb_utf8_filename);
dpbBuffer.push_back(0); // no filename here, it is passed to functions directly
ISC_STATUS_ARRAY status; /* status vector */
ISC_STATUS aErr; const OString sFirebirdURL = OUStringToOString(m_sFirebirdURL, RTL_TEXTENCODING_UTF8); if (bIsNewDatabase)
{
aErr = isc_create_database(status,
sFirebirdURL.getLength(),
sFirebirdURL.getStr(),
&m_aDBHandle,
dpbBuffer.size(),
dpbBuffer.c_str(),
0); if (aErr)
{
evaluateStatusVector(status, u"isc_create_database", *this);
}
} else
{ if (m_bIsEmbedded && !bIsFdbStored) // We need to restore the .fbk first
{
runBackupService(isc_action_svc_restore);
}
if (m_bIsEmbedded) // Add DocumentEventListener to save the .fdb as needed
{ // We need to attach as a document listener in order to be able to store // the temporary db back into the .odb when saving
uno::Reference<XDocumentEventBroadcaster> xBroadcaster(m_xParentDocument, UNO_QUERY);
if (xBroadcaster.is())
xBroadcaster->addDocumentEventListener(this); else
assert(false);
}
} catch (const Exception&)
{ throw;
} catch (const std::exception&)
{ throw;
} catch (...) // const Firebird::Exception& firebird throws this, but doesn't install the fb_exception.h that declares it
// the pre if(m_aTypeInfo.empty())
buildTypeInfo();
// create a statement // the statement can only be executed once
Reference< XStatement > xReturn = new OStatement(this);
m_aStatements.emplace_back(xReturn); return xReturn;
}
// TODO: is this sensible? If we have changed parameters then transaction // is lost... if (m_aTransactionHandle)
{
disposeStatements();
isc_rollback_transaction(status_vector, &m_aTransactionHandle);
}
char aTransactionIsolation = 0; switch (m_aTransactionIsolation)
{ // TODO: confirm that these are correct. case TransactionIsolation::READ_UNCOMMITTED:
aTransactionIsolation = isc_tpb_concurrency; break; case TransactionIsolation::READ_COMMITTED:
aTransactionIsolation = isc_tpb_read_committed; break; case TransactionIsolation::REPEATABLE_READ: case TransactionIsolation::SERIALIZABLE:
aTransactionIsolation = isc_tpb_consistency; break; default:
assert( false ); // We must have a valid TransactionIsolation.
}
// You cannot pass an empty tpb parameter so we have to do some pointer // arithmetic to avoid problems. (i.e. aTPB[x] = 0 is invalid) char aTPB[5]; char* pTPB = aTPB;
// here we have to create the class with biggest interface // The answer is 42 :-)
rtl::Reference< ODatabaseMetaData > xMetaData = m_xMetaData.get(); if(!xMetaData.is())
{
xMetaData = new ODatabaseMetaData(this); // need the connection because it can return it
m_xMetaData = xMetaData.get();
}
ISC_STATUS_ARRAY status; /* status vector */ if (m_aTransactionHandle)
{ // TODO: confirm whether we need to ask the user here.
isc_rollback_transaction(status, &m_aTransactionHandle);
}
if (m_aDBHandle)
{ if (isc_detach_database(status, &m_aDBHandle))
{
evaluateStatusVector(status, u"isc_detach_database", *this);
}
}
storeDatabase();
cppu::WeakComponentImplHelperBase::disposing();
m_pDatabaseFileDir.reset();
}
void Connection::storeDatabase()
{
MutexGuard aGuard(m_aMutex); if (m_bIsEmbedded && m_xEmbeddedStorage.is())
{
SAL_INFO("connectivity.firebird", "Writing .fbk from running db"); try
{
runBackupService(isc_action_svc_backup);
} catch (const SQLException& e)
{ auto a = cppu::getCaughtException(); throw WrappedTargetRuntimeException(e.Message, e.Context, a);
}
Reference<XStream> xDBStream(
m_xEmbeddedStorage->openStreamElement(our_sFBKLocation, ElementModes::WRITE)); usingnamespace ::comphelper; const Reference<XComponentContext>& xContext = comphelper::getProcessComponentContext();
Reference<XInputStream> xInputStream; if (!xContext.is()) return;
xInputStream = OStorageHelper::GetInputStreamFromURL(m_sFBKPath, xContext); if (xInputStream.is())
OStorageHelper::CopyInputToOutput(xInputStream, xDBStream->getOutputStream());
}
}
// m_xCatalog is a weak reference. Reuse it if it still exists.
rtl::Reference< Catalog > xCatalog = m_xCatalog.get(); if (!xCatalog.is())
{
xCatalog = new Catalog(this);
m_xCatalog = xCatalog.get();
} return xCatalog;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.