.gitignore | 2 Repository.mk | 4 accessibility/source/helper/accresmgr.cxx | 3 avmedia/Library_avmedia.mk | 1 avmedia/source/framework/mediamisc.cxx | 33 - avmedia/source/inc/mediamisc.hxx | 7 basctl/source/basicide/basicmod.hxx | 4 basctl/source/basicide/iderdll.cxx | 4 basic/source/sbx/sbxscan.cxx | 5 chart2/Library_chartcore.mk | 1 chart2/source/inc/ResourceManager.hxx | 38 - chart2/source/tools/ResId.cxx | 3 chart2/source/tools/ResourceManager.cxx | 34 - connectivity/source/drivers/firebird/Blob.cxx | 65 +++ connectivity/source/drivers/firebird/Blob.hxx | 4 connectivity/source/drivers/firebird/Clob.cxx | 92 +++- connectivity/source/drivers/firebird/Clob.hxx | 2 connectivity/source/drivers/firebird/DatabaseMetaData.cxx | 111 +++-- connectivity/source/drivers/firebird/PreparedStatement.cxx | 111 +++++ connectivity/source/drivers/firebird/PreparedStatement.hxx | 1 connectivity/source/drivers/firebird/ResultSet.cxx | 17 connectivity/source/drivers/firebird/ResultSetMetaData.cxx | 59 ++- connectivity/source/drivers/firebird/ResultSetMetaData.hxx | 1 connectivity/source/drivers/firebird/Tables.cxx | 29 + connectivity/source/drivers/firebird/Util.cxx | 193 +++++----- connectivity/source/drivers/firebird/Util.hxx | 45 ++ connectivity/source/parse/sqlbison.y | 4 connectivity/source/parse/sqlflex.l | 3 cui/source/factory/cuiresmgr.cxx | 3 dbaccess/source/core/resource/core_resource.cxx | 3 desktop/source/lib/init.cxx | 6 desktop/source/lib/lokinteractionhandler.cxx | 12 editeng/source/editeng/eerdll.cxx | 8 embeddedobj/source/msole/olevisual.cxx | 6 extensions/source/inc/componentmodule.cxx | 3 extensions/source/propctrlr/modulepcr.cxx | 3 extensions/source/scanner/sanedlg.cxx | 3 extensions/source/scanner/scanwin.cxx | 10 external/cairo/cairo/cairo-1.10.2.patch | 137 ++++++- external/cairo/pixman/pixman-0.24.4.patch | 72 +++ filter/source/pdf/impdialog.cxx | 9 filter/source/xsltdialog/xmlfiltersettingsdialog.cxx | 3 forms/source/resource/frm_resource.cxx | 3 formula/source/core/resource/core_resource.cxx | 3 fpicker/inc/fpsofficeResMgr.hxx | 3 framework/source/fwe/classes/fwkresid.cxx | 3 include/basic/sbdef.hxx | 2 include/editeng/eerdll.hxx | 1 include/rtl/alloc.h | 42 +- include/sfx2/module.hxx | 8 include/sfx2/viewsh.hxx | 2 include/svl/languageoptions.hxx | 2 include/svtools/svtresid.hxx | 2 include/svx/dialmgr.hxx | 2 libreofficekit/Executable_tilebench.mk | 1 libreofficekit/Module_libreofficekit.mk | 5 libreofficekit/qa/tilebench/tilebench.cxx | 157 ++++++-- officecfg/registry/data/org/openoffice/Office/TableWizard.xcu | 76 +-- oox/source/ole/axcontrol.cxx | 7 reportdesign/source/core/resource/core_resource.cxx | 3 sal/inc/rtllifecycle.h | 4 sal/qa/rtl/alloc/rtl_alloc.cxx | 4 sal/rtl/alloc_cache.cxx | 10 sal/rtl/strimp.cxx | 53 +- sc/source/ui/app/scmod.cxx | 2 sccomp/source/solver/SolverComponent.cxx | 3 sccomp/source/solver/SwarmSolver.cxx | 3 sd/source/ui/app/sdmod.cxx | 2 sdext/source/pdfimport/inc/pdfiprocessor.hxx | 10 sdext/source/pdfimport/tree/pdfiprocessor.cxx | 18 sfx2/source/appl/module.cxx | 16 sfx2/source/bastyp/sfxresid.cxx | 4 sfx2/source/dialog/basedlgs.cxx | 4 sfx2/source/dialog/tabdlg.cxx | 2 sfx2/source/doc/sfxbasemodel.cxx | 4 sfx2/source/view/viewsh.cxx | 7 solenv/vs/LibreOffice.natvis | 48 +- starmath/source/smmod.cxx | 2 svl/source/config/languageoptions.cxx | 8 svl/source/misc/getstringresource.cxx | 3 svtools/source/misc/svtresid.cxx | 5 svx/source/dialog/dialmgr.cxx | 5 sw/inc/section.hxx | 2 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 3 sw/qa/python/text_portion_enumeration_test.py | 21 - sw/source/core/docnode/ndsect.cxx | 2 sw/source/core/undo/SwUndoPageDesc.cxx | 114 ----- sw/source/core/unocore/unoportenum.cxx | 111 +++++ sw/source/uibase/app/swmodule.cxx | 2 tools/source/memtools/multisel.cxx | 19 vcl/headless/svpbmp.cxx | 5 vcl/headless/svpgdi.cxx | 118 +++++- vcl/inc/headless/svpgdi.hxx | 4 vcl/qa/cppunit/BitmapTest.cxx | 9 vcl/qa/cppunit/svm/svmtest.cxx | 12 vcl/source/app/settings.cxx | 6 vcl/source/control/imp_listbox.cxx | 1 vcl/source/outdev/font.cxx | 1 writerperfect/Library_writerperfect.mk | 1 writerperfect/inc/WPFTResMgr.hxx | 7 writerperfect/source/common/WPFTResMgr.cxx | 11 xmlsecurity/inc/resourcemanager.hxx | 4 xmlsecurity/source/dialogs/resourcemanager.cxx | 6 103 files changed, 1423 insertions(+), 729 deletions(-)
New commits: commit 7ff6b33f740ff28d6821863978df1ff82fa7616a Author: Jan Holesovsky <[email protected]> Date: Wed Jan 3 17:49:25 2018 +0100 lokdialog: Use only one of the installed langpacks when setting locale. Change-Id: I446775b121b7806a549f4dbbaa1f2dcf019d9bc2 Reviewed-on: https://gerrit.libreoffice.org/47334 Reviewed-by: Michael Meeks <[email protected]> Tested-by: Jan Holesovsky <[email protected]> diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 0c83f5faee15..e7a0f6d7fec1 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -344,7 +344,7 @@ public: virtual vcl::Window* GetEditWindowForActiveOLEObj() const override; /// Set the LibreOfficeKit language of this view. - void SetLOKLanguageTag(const OUString& rBcp47LanguageTag) { maLOKLanguageTag = LanguageTag(rBcp47LanguageTag, true); } + void SetLOKLanguageTag(const OUString& rBcp47LanguageTag); /// Get the LibreOfficeKit language of this view. const LanguageTag& GetLOKLanguageTag() const { return maLOKLanguageTag; } }; diff --git a/include/svl/languageoptions.hxx b/include/svl/languageoptions.hxx index f386cb6b0e00..389eae8aa346 100644 --- a/include/svl/languageoptions.hxx +++ b/include/svl/languageoptions.hxx @@ -132,7 +132,7 @@ public: }; OUString SVL_DLLPUBLIC getInstalledLocaleForLanguage(css::uno::Sequence<OUString> const & installed, OUString const & locale); -OUString SVL_DLLPUBLIC getInstalledLocaleForSystemUILanguage(css::uno::Sequence<OUString> const & installed); +OUString SVL_DLLPUBLIC getInstalledLocaleForSystemUILanguage(css::uno::Sequence<OUString> const & installed, const OUString& rPreferredLocale = OUString()); #endif // INCLUDED_SVL_LANGUAGEOPTIONS_HXX diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index ad0fce0a6466..3eb162ffe642 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -57,6 +57,7 @@ #include <vcl/commandinfoprovider.hxx> #include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <officecfg/Setup.hxx> #include <sfx2/app.hxx> #include <sfx2/viewsh.hxx> #include "viewimp.hxx" @@ -1488,6 +1489,12 @@ vcl::Window* SfxViewShell::GetEditWindowForActiveOLEObj() const return pEditWin; } +void SfxViewShell::SetLOKLanguageTag(const OUString& rBcp47LanguageTag) +{ + css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames()); + maLOKLanguageTag = LanguageTag(getInstalledLocaleForSystemUILanguage(inst, rBcp47LanguageTag), true).makeFallback(); +} + void SfxViewShell::NotifyCursor(SfxViewShell* /*pViewShell*/) const { } diff --git a/svl/source/config/languageoptions.cxx b/svl/source/config/languageoptions.cxx index 9f9fe4513819..faa573069e5c 100644 --- a/svl/source/config/languageoptions.cxx +++ b/svl/source/config/languageoptions.cxx @@ -283,9 +283,13 @@ OUString getInstalledLocaleForLanguage(css::uno::Sequence<OUString> const & inst return OUString(); } -OUString getInstalledLocaleForSystemUILanguage(const css::uno::Sequence<OUString>& rLocaleElementNames) +OUString getInstalledLocaleForSystemUILanguage(const css::uno::Sequence<OUString>& rLocaleElementNames, const OUString& rPreferredLocale) { - OUString locale = getInstalledLocaleForLanguage(rLocaleElementNames, officecfg::System::L10N::UILocale::get()); + OUString aPreferredLocale(rPreferredLocale); + if (aPreferredLocale.isEmpty()) + aPreferredLocale = officecfg::System::L10N::UILocale::get(); + + OUString locale = getInstalledLocaleForLanguage(rLocaleElementNames, aPreferredLocale); if (locale.isEmpty()) locale = getInstalledLocaleForLanguage(rLocaleElementNames, "en-US"); if (locale.isEmpty() && rLocaleElementNames.hasElements()) commit 23b811466e53a30efde898a6fd9b3a55aff33a38 Author: Jan Holesovsky <[email protected]> Date: Wed Jan 3 14:08:55 2018 +0100 lokdialog: Allow language switching in SfxModule(s). Change-Id: Icef0b3610c3bfa858cdd61de6ef3f5edc1e3c96b Reviewed-on: https://gerrit.libreoffice.org/47385 Tested-by: Jenkins <[email protected]> Reviewed-by: Jan Holesovsky <[email protected]> (cherry picked from commit 028fd03cdf4d3d8072289a5c4d476435c18f90d0) diff --git a/basctl/source/basicide/basicmod.hxx b/basctl/source/basicide/basicmod.hxx index 7dcee5a16420..d94a2198d440 100644 --- a/basctl/source/basicide/basicmod.hxx +++ b/basctl/source/basicide/basicmod.hxx @@ -29,8 +29,8 @@ namespace basctl class Module : public SfxModule { public: - Module(const std::locale& rResLocale, SfxObjectFactory *pObjFact) - : SfxModule(rResLocale, {pObjFact}) + Module(const OString& rResName, SfxObjectFactory *pObjFact) + : SfxModule(rResName, {pObjFact}) { } }; diff --git a/basctl/source/basicide/iderdll.cxx b/basctl/source/basicide/iderdll.cxx index 19d21c32eedb..b80ce1f38970 100644 --- a/basctl/source/basicide/iderdll.cxx +++ b/basctl/source/basicide/iderdll.cxx @@ -118,9 +118,7 @@ Dll::Dll () : { SfxObjectFactory& rFactory = DocShell::Factory(); - std::locale loc = Translate::Create("basctl"); - - auto pModule = o3tl::make_unique<Module>(loc, &rFactory); + auto pModule = o3tl::make_unique<Module>("basctl", &rFactory); SfxModule* pMod = pModule.get(); SfxApplication::SetModule(SfxToolsModule::Basic, std::move(pModule)); diff --git a/include/sfx2/module.hxx b/include/sfx2/module.hxx index de487dafaa3f..352d1e46ba6f 100644 --- a/include/sfx2/module.hxx +++ b/include/sfx2/module.hxx @@ -52,13 +52,11 @@ namespace com { namespace sun { namespace star { namespace frame { class SFX2_DLLPUBLIC SfxModule : public SfxShell { private: - std::locale m_aResLocale; - // Warning this cannot be turned into a unique_ptr. // SfxInterface destruction in the SfxSlotPool refers again to pImpl after deletion of pImpl has commenced. See tdf#100270 SfxModule_Impl* pImpl; - SAL_DLLPRIVATE void Construct_Impl(); + SAL_DLLPRIVATE void Construct_Impl(const OString& rResName); public: SFX_DECL_INTERFACE(SFX_INTERFACE_SFXMODULE) @@ -69,10 +67,10 @@ private: public: - SfxModule(const std::locale& rResLocale, std::initializer_list<SfxObjectFactory*> pFactoryList); + SfxModule(const OString& rResName, std::initializer_list<SfxObjectFactory*> pFactoryList); virtual ~SfxModule() override; - const std::locale& GetResLocale() const { return m_aResLocale; } + std::locale GetResLocale() const; SfxSlotPool* GetSlotPool() const; void RegisterToolBoxControl(const SfxTbxCtrlFactory&); diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index aba269d29aa4..a78716d3fa66 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -137,7 +137,7 @@ void ScModule::InitInterface_Impl() } ScModule::ScModule( SfxObjectFactory* pFact ) : - SfxModule( Translate::Create("sc"), {pFact} ), + SfxModule("sc", {pFact}), aIdleTimer("sc ScModule IdleTimer"), aSpellIdle("sc ScModule SpellIdle"), mpDragData(new ScDragData), diff --git a/sd/source/ui/app/sdmod.cxx b/sd/source/ui/app/sdmod.cxx index 61dd5e6b10a4..9d9eaa53aecb 100644 --- a/sd/source/ui/app/sdmod.cxx +++ b/sd/source/ui/app/sdmod.cxx @@ -65,7 +65,7 @@ void SdModule::InitInterface_Impl() // Ctor SdModule::SdModule(SfxObjectFactory* pFact1, SfxObjectFactory* pFact2 ) -: SfxModule( Translate::Create("sd"), {pFact1, pFact2} ), +: SfxModule("sd", {pFact1, pFact2}), pTransferClip(nullptr), pTransferDrag(nullptr), pTransferSelection(nullptr), diff --git a/sfx2/source/appl/module.cxx b/sfx2/source/appl/module.cxx index ef37f8e41ada..3fb4376cc7a1 100644 --- a/sfx2/source/appl/module.cxx +++ b/sfx2/source/appl/module.cxx @@ -48,6 +48,7 @@ public: SfxTbxCtrlFactArr_Impl* pTbxCtrlFac; SfxStbCtrlFactArr_Impl* pStbCtrlFac; SfxChildWinFactArr_Impl* pFactArr; + OString maResName; SfxModule_Impl(); ~SfxModule_Impl(); @@ -68,11 +69,10 @@ SfxModule_Impl::~SfxModule_Impl() SFX_IMPL_SUPERCLASS_INTERFACE(SfxModule, SfxShell) -SfxModule::SfxModule(const std::locale& rLocale, std::initializer_list<SfxObjectFactory*> pFactoryList) - : m_aResLocale(rLocale) - , pImpl(nullptr) +SfxModule::SfxModule(const OString& rResName, std::initializer_list<SfxObjectFactory*> pFactoryList) + : pImpl(nullptr) { - Construct_Impl(); + Construct_Impl(rResName); for (auto pFactory : pFactoryList) { if (pFactory) @@ -80,7 +80,7 @@ SfxModule::SfxModule(const std::locale& rLocale, std::initializer_list<SfxObject } } -void SfxModule::Construct_Impl() +void SfxModule::Construct_Impl(const OString& rResName) { SfxApplication *pApp = SfxApplication::GetOrCreate(); pImpl = new SfxModule_Impl; @@ -89,6 +89,7 @@ void SfxModule::Construct_Impl() pImpl->pTbxCtrlFac=nullptr; pImpl->pStbCtrlFac=nullptr; pImpl->pFactArr=nullptr; + pImpl->maResName = rResName; SetPool( &pApp->GetPool() ); } @@ -102,6 +103,11 @@ SfxModule::~SfxModule() } } +std::locale SfxModule::GetResLocale() const +{ + return Translate::Create(pImpl->maResName.getStr()); +} + SfxSlotPool* SfxModule::GetSlotPool() const { return pImpl->pSlotPool; diff --git a/starmath/source/smmod.cxx b/starmath/source/smmod.cxx index 08bec54144cf..02a8fec7a572 100644 --- a/starmath/source/smmod.cxx +++ b/starmath/source/smmod.cxx @@ -119,7 +119,7 @@ void SmModule::InitInterface_Impl() } SmModule::SmModule(SfxObjectFactory* pObjFact) - : SfxModule(Translate::Create("sm"), {pObjFact}) + : SfxModule("sm", {pObjFact}) { SetName("StarMath"); diff --git a/sw/source/uibase/app/swmodule.cxx b/sw/source/uibase/app/swmodule.cxx index 71264ffd5bea..b4c271d66852 100644 --- a/sw/source/uibase/app/swmodule.cxx +++ b/sw/source/uibase/app/swmodule.cxx @@ -146,7 +146,7 @@ using namespace ::com::sun::star::uno; SwModule::SwModule( SfxObjectFactory* pWebFact, SfxObjectFactory* pFact, SfxObjectFactory* pGlobalFact ) - : SfxModule( Translate::Create("sw"), {pWebFact, pFact, pGlobalFact} ), + : SfxModule("sw", {pWebFact, pFact, pGlobalFact}), m_pModuleConfig(nullptr), m_pUsrPref(nullptr), m_pWebUsrPref(nullptr), commit 5eca99187e576389a33e73e3053a29dfd2b417e0 Author: Mike Kaganski <[email protected]> Date: Thu Jan 4 14:11:05 2018 +0100 Remove redundant control flow branch Change-Id: I5f63f2a7ad6eb6bf85b21b6936a1488ce13ccc93 Reviewed-on: https://gerrit.libreoffice.org/47394 Tested-by: Jenkins <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> (cherry picked from commit d86d3caf9853e930eb686b63309a7cc6c29cc0d2) diff --git a/embeddedobj/source/msole/olevisual.cxx b/embeddedobj/source/msole/olevisual.cxx index a9faa3a83eeb..820e39c2f7f0 100644 --- a/embeddedobj/source/msole/olevisual.cxx +++ b/embeddedobj/source/msole/olevisual.cxx @@ -345,12 +345,8 @@ embed::VisualRepresentation SAL_CALL OleEmbeddedObject::getPreferredVisualRepres SetVisReplInStream( m_xCachedVisualRepresentation.is() ); } - if ( m_xCachedVisualRepresentation.is() ) - { - return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); - } #ifdef _WIN32 - else if ( m_pOleComponent ) + if ( !m_xCachedVisualRepresentation.is() && m_pOleComponent ) { try { commit 22779e8220848a5d52ee313a180535d4f6359ad0 Author: Miklos Vajna <[email protected]> Date: Wed Jan 3 14:55:30 2018 +0100 sfx2: improve reported error message in SfxBaseModel::impl_store() Old: com.sun.star.io.IOException: SfxBaseModel::impl_store <file:///c:/lo/bugs/saved.xhtml> failed: 0x507 New: com.sun.star.io.IOException: SfxBaseModel::impl_store <file:///c:/lo/bugs/saved.xhtml> failed: 0x507(Error Area:Io Class:Access Code:1287) It's much easier to find the relevant define in include/vcl/errcode.hxx based on the new output. Change-Id: I7d98dcf1ead10264672b45de570e51a153090499 Reviewed-on: https://gerrit.libreoffice.org/47319 Tested-by: Jenkins <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> (cherry picked from commit 050c0422b9c8a859d886748ae70e99274d1d9afa) diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx index 7cb1076485a5..577562aa974c 100644 --- a/sfx2/source/doc/sfxbasemodel.cxx +++ b/sfx2/source/doc/sfxbasemodel.cxx @@ -3019,8 +3019,10 @@ void SfxBaseModel::impl_store( const OUString& sURL SfxGetpApp()->NotifyEvent( SfxEventHint( bSaveTo ? SfxEventHintId::SaveToDocFailed : SfxEventHintId::SaveAsDocFailed, GlobalEventConfig::GetEventName( bSaveTo ? GlobalEventId::SAVETODOCFAILED : GlobalEventId::SAVEASDOCFAILED), m_pData->m_pObjectShell.get() ) ); + std::stringstream aErrCode; + aErrCode << nErrCode; throw task::ErrorCodeIOException( - "SfxBaseModel::impl_store <" + sURL + "> failed: " + nErrCode.toHexString(), + "SfxBaseModel::impl_store <" + sURL + "> failed: " + OUString::fromUtf8(aErrCode.str().c_str()), Reference< XInterface >(), sal_uInt32(nErrCode)); } } commit 6f6814b9a354f712a4069932271dc7ba578774fd Author: Tor Lillqvist <[email protected]> Date: Tue Jan 2 18:46:33 2018 +0200 tdf#104986: Add MILLISECOND, WEEKDAY, and YEARDAY tokens for Firebird Change-Id: I2ba866c408dbf49f1655cc08cc5d0df840eaf01e Reviewed-on: https://gerrit.libreoffice.org/47271 Tested-by: Jenkins <[email protected]> Reviewed-by: Tor Lillqvist <[email protected]> (cherry picked from commit 72ff62a13af402d19e6e53b809b29033a985c04a) diff --git a/connectivity/source/parse/sqlbison.y b/connectivity/source/parse/sqlbison.y index 2c55bae0f66b..0f21bcc6fcc9 100644 --- a/connectivity/source/parse/sqlbison.y +++ b/connectivity/source/parse/sqlbison.y @@ -146,8 +146,8 @@ using namespace connectivity; /* time and date functions */ %token <pParseNode> SQL_TOKEN_CURRENT_DATE SQL_TOKEN_CURRENT_TIME SQL_TOKEN_CURRENT_TIMESTAMP SQL_TOKEN_CURDATE SQL_TOKEN_CURTIME %token <pParseNode> SQL_TOKEN_DAYNAME SQL_TOKEN_DAYOFMONTH SQL_TOKEN_DAYOFWEEK SQL_TOKEN_DAYOFYEAR SQL_TOKEN_EXTRACT -%token <pParseNode> SQL_TOKEN_HOUR SQL_TOKEN_MINUTE SQL_TOKEN_MONTH SQL_TOKEN_MONTHNAME SQL_TOKEN_NOW SQL_TOKEN_QUARTER SQL_TOKEN_DATEDIFF -%token <pParseNode> SQL_TOKEN_SECOND SQL_TOKEN_TIMESTAMPADD SQL_TOKEN_TIMESTAMPDIFF SQL_TOKEN_TIMEVALUE SQL_TOKEN_WEEK SQL_TOKEN_YEAR +%token <pParseNode> SQL_TOKEN_HOUR SQL_TOKEN_MILLISECOND SQL_TOKEN_MINUTE SQL_TOKEN_MONTH SQL_TOKEN_MONTHNAME SQL_TOKEN_NOW SQL_TOKEN_QUARTER SQL_TOKEN_DATEDIFF +%token <pParseNode> SQL_TOKEN_SECOND SQL_TOKEN_TIMESTAMPADD SQL_TOKEN_TIMESTAMPDIFF SQL_TOKEN_TIMEVALUE SQL_TOKEN_WEEK SQL_TOKEN_WEEKDAY SQL_TOKEN_YEAR SQL_TOKEN_YEARDAY /* numeric functions */ %token <pParseNode> SQL_TOKEN_ABS SQL_TOKEN_ACOS SQL_TOKEN_ASIN SQL_TOKEN_ATAN SQL_TOKEN_ATAN2 SQL_TOKEN_CEILING diff --git a/connectivity/source/parse/sqlflex.l b/connectivity/source/parse/sqlflex.l index 9d9f119fd640..5d8a59c27844 100644 --- a/connectivity/source/parse/sqlflex.l +++ b/connectivity/source/parse/sqlflex.l @@ -260,6 +260,7 @@ LOWER {SQL_NEW_KEYWORD(SQL_TOKEN_LOWER); } LTRIM {SQL_NEW_KEYWORD(SQL_TOKEN_LTRIM); } MAX {SQL_NEW_KEYWORD(SQL_TOKEN_MAX); } +MILLISECOND {SQL_NEW_KEYWORD(SQL_TOKEN_MILLISECOND); } MIN {SQL_NEW_KEYWORD(SQL_TOKEN_MIN); } MINUTE {SQL_NEW_KEYWORD(SQL_TOKEN_MINUTE); } MOD {SQL_NEW_KEYWORD(SQL_TOKEN_MOD); } @@ -394,6 +395,7 @@ VALUES {SQL_NEW_KEYWORD(SQL_TOKEN_VALUES); } VIEW {SQL_NEW_KEYWORD(SQL_TOKEN_VIEW); } WEEK {SQL_NEW_KEYWORD(SQL_TOKEN_WEEK); } +WEEKDAY {SQL_NEW_KEYWORD(SQL_TOKEN_WEEKDAY); } WHEN {SQL_NEW_KEYWORD(SQL_TOKEN_WHEN); } WHERE {SQL_NEW_KEYWORD(SQL_TOKEN_WHERE); } WITH {SQL_NEW_KEYWORD(SQL_TOKEN_WITH); } @@ -402,6 +404,7 @@ WITHOUT {SQL_NEW_KEYWORD(SQL_TOKEN_WITHOUT); } WORK {SQL_NEW_KEYWORD(SQL_TOKEN_WORK); } YEAR {SQL_NEW_KEYWORD(SQL_TOKEN_YEAR); } +YEARDAY {SQL_NEW_KEYWORD(SQL_TOKEN_YEARDAY); } ZONE {SQL_NEW_KEYWORD(SQL_TOKEN_ZONE); } commit 72922b519becc66a285ae7ae82aadb4eb4d41992 Author: Tor Lillqvist <[email protected]> Date: Tue Jan 2 16:54:40 2018 +0200 tdf#71007: Pass also fractional seconds to/from Firebird We know that ISC_TIME is simply in units of seconds/ISC_TIME_SECONDS_PRECISION. Change-Id: I2896f53c2d32a773c535e19f55dd1314abd18ec9 Reviewed-on: https://gerrit.libreoffice.org/47266 Tested-by: Jenkins <[email protected]> Reviewed-by: Tor Lillqvist <[email protected]> (cherry picked from commit e0a22d47d281f61f51ead6d2831cd53c15036ffe) diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index afe1fa3229a6..f97895ec530e 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.cxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -463,6 +463,10 @@ void SAL_CALL OPreparedStatement::setTime( sal_Int32 nIndex, const css::util::Ti ISC_TIME aISCTime; isc_encode_sql_time(&aCTime, &aISCTime); + // Here we "know" that ISC_TIME is simply in units of seconds/ISC_TIME_SECONDS_PRECISION with no + // other funkiness, so we can simply add the fraction of a second. + aISCTime += rTime.NanoSeconds / (1000000000 / ISC_TIME_SECONDS_PRECISION); + setValue< ISC_TIME >(nIndex, aISCTime, SQL_TYPE_TIME); } @@ -479,6 +483,9 @@ void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 nIndex, const DateTime& ISC_TIMESTAMP aISCTimestamp; isc_encode_timestamp(&aCTime, &aISCTimestamp); + // As in previous function + aISCTimestamp.timestamp_time += rTimestamp.NanoSeconds / (1000000000 / ISC_TIME_SECONDS_PRECISION); + setValue< ISC_TIMESTAMP >(nIndex, aISCTimestamp, SQL_TIMESTAMP); } diff --git a/connectivity/source/drivers/firebird/ResultSet.cxx b/connectivity/source/drivers/firebird/ResultSet.cxx index 9e8387d39a3d..20fe2a4dab1e 100644 --- a/connectivity/source/drivers/firebird/ResultSet.cxx +++ b/connectivity/source/drivers/firebird/ResultSet.cxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -526,9 +526,12 @@ Time OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*n struct tm aCTime; isc_decode_sql_time(&aISCTime, &aCTime); - // first field is nanoseconds -- not supported in firebird or struct tm. + // First field is nanoseconds. // last field denotes UTC (true) or unknown (false) - return Time(0, aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, false); + // Here we "know" that ISC_TIME is simply in units of seconds/ISC_TIME_SECONDS_PRECISION + // with no other funkiness, so we can get the fractional seconds easily. + return Time((aISCTime % ISC_TIME_SECONDS_PRECISION) * (1000000000 / ISC_TIME_SECONDS_PRECISION), + aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, false); } else { @@ -546,7 +549,8 @@ DateTime OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT struct tm aCTime; isc_decode_timestamp(&aISCTimestamp, &aCTime); - return DateTime(0, //nanoseconds, not supported + // Ditto here, see comment in previous function about ISC_TIME and ISC_TIME_SECONDS_PRECISION. + return DateTime((aISCTimestamp.timestamp_time % ISC_TIME_SECONDS_PRECISION) * (1000000000 / ISC_TIME_SECONDS_PRECISION), //nanoseconds aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, commit c35c0630e43025308bc1cbbf50019458a926f3a7 Author: Tor Lillqvist <[email protected]> Date: Mon Jan 1 15:14:20 2018 +0200 Reduce large VARCHAR columns of the wizard sample databases to fit Firebird The maximum size of a VARCHAR column in Firebird is 32765 bytes [sic]. We use the UTF8 character set and that means 8190 characters as each character might take four bytes. The maximum size of a row in Firebird is 64 KB [sic]. Avoids errors when creating sample tables using the wizard using just the default values. If the varchar column lengths are under 8190 but the total row size is too large you do get a relatively helpful error message "new record size of <N> bytes is too big", but if you try use a too large size for a varchar column, just some "SQL error code = -204", "Impmentation limit exceeded", etc. Change-Id: I17c2bed4fc098f4e159822f6f81242aae274da7b Reviewed-on: https://gerrit.libreoffice.org/47232 Tested-by: Jenkins <[email protected]> Reviewed-by: Tor Lillqvist <[email protected]> (cherry picked from commit ee29c944868a578b002103bb58595029bf385473) diff --git a/officecfg/registry/data/org/openoffice/Office/TableWizard.xcu b/officecfg/registry/data/org/openoffice/Office/TableWizard.xcu index 2b1876005ef8..e748eda1d272 100644 --- a/officecfg/registry/data/org/openoffice/Office/TableWizard.xcu +++ b/officecfg/registry/data/org/openoffice/Office/TableWizard.xcu @@ -513,7 +513,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -987,7 +987,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -1379,7 +1379,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -1661,7 +1661,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -2152,7 +2152,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -2956,7 +2956,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -3158,7 +3158,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -3359,7 +3359,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="clientID" oor:op="replace"> @@ -3513,7 +3513,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="eventtypeID" oor:op="replace"> @@ -3710,7 +3710,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -3912,7 +3912,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -4052,7 +4052,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -4229,7 +4229,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -4649,7 +4649,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -4984,7 +4984,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="nextscheduledmaintenance" oor:op="replace"> @@ -5294,7 +5294,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -5338,7 +5338,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="startdate" oor:op="replace"> @@ -5383,7 +5383,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -5884,7 +5884,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="dateupdated" oor:op="replace"> @@ -6174,7 +6174,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -6345,7 +6345,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>4000</value> </prop> </node> <node oor:name="ingredients" oor:op="replace"> @@ -6362,7 +6362,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>4000</value> </prop> </node> <node oor:name="instructions" oor:op="replace"> @@ -6379,7 +6379,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>4000</value> </prop> </node> <node oor:name="utensils" oor:op="replace"> @@ -6413,7 +6413,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>2000</value> </prop> </node> </node> @@ -6691,7 +6691,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -6893,7 +6893,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -7061,7 +7061,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -7306,7 +7306,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="notes" oor:op="replace"> @@ -7323,7 +7323,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -7562,7 +7562,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="notes" oor:op="replace"> @@ -7579,7 +7579,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -7849,7 +7849,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -8006,7 +8006,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> <node oor:name="photo" oor:op="replace"> @@ -8037,7 +8037,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -8163,7 +8163,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -8286,7 +8286,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -8482,7 +8482,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> @@ -8675,7 +8675,7 @@ <value>-1</value> </prop> <prop oor:name="Precision"> - <value>65000</value> + <value>8000</value> </prop> </node> </node> commit 6dc0f9b66987a314540aac11061b361423a054f6 Author: Tamás Zolnai <[email protected]> Date: Sat Dec 30 13:49:18 2017 +0100 Enable test for exporting text color of activeX checkbox control It's fixed in: 05f72a2a39fccb58f59b99ebfd3e7d0d8ff354e9 Change-Id: I5f82b1bd5dc0b2155398e4fc74da21f1a96e1d56 Reviewed-on: https://gerrit.libreoffice.org/47193 Tested-by: Jenkins <[email protected]> Reviewed-by: Tamás Zolnai <[email protected]> (cherry picked from commit 6246d44680ec9b4cc132614e664c4cb88095b09e) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index dddc7b2b918c..f71241a025d3 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -922,8 +922,7 @@ DECLARE_OOXMLEXPORT_TEST( testActiveXCheckbox, "activex_checkbox.docx" ) CPPUNIT_ASSERT_EQUAL( sal_Int32( 0x316AC5 ), getProperty<sal_Int32>(xPropertySet, "BackgroundColor") ); // Check Text color (active border system color) - if(!mbExported) // Bug: text color is not exported - CPPUNIT_ASSERT_EQUAL(sal_Int32(0xD4D0C8), getProperty<sal_Int32>(xPropertySet, "TextColor")); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0xD4D0C8), getProperty<sal_Int32>(xPropertySet, "TextColor")); // Check state of the checkbox CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xPropertySet, "State")); commit e887d2bbd81e2c1188b6fd20d06689fda1604e23 Author: Bán Róbert <[email protected]> Date: Fri Dec 29 23:49:00 2017 +0100 tdf#113788 ActiveX controls' text color is not exported to DOCX The convertFromProperties function does not set the text color. Background color is a similar property and it is handled similarly. Change-Id: I2c1bff6198640b9a30f70d9db641425166ced992 Reviewed-on: https://gerrit.libreoffice.org/47185 Tested-by: Jenkins <[email protected]> Reviewed-by: Tamás Zolnai <[email protected]> (cherry picked from commit 05f72a2a39fccb58f59b99ebfd3e7d0d8ff354e9) diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx index 7ab805691c82..a697fddfe33c 100644 --- a/oox/source/ole/axcontrol.cxx +++ b/oox/source/ole/axcontrol.cxx @@ -1585,6 +1585,7 @@ void AxToggleButtonModel::convertFromProperties( PropertySet& rPropSet, const Co setFlag( mnFlags, AX_FLAGS_WORDWRAP, bRes ); ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); // need to process the image if one exists ControlConverter::convertToAxState( rPropSet, maValue, mnMultiSelect, API_DEFAULTSTATE_BOOLEAN ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); @@ -1660,6 +1661,7 @@ void AxCheckBoxModel::convertFromProperties( PropertySet& rPropSet, const Contro ControlConverter::convertToAxVisualEffect( rPropSet, mnSpecialEffect ); ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); // need to process the image if one exists ControlConverter::convertToAxState( rPropSet, maValue, mnMultiSelect, API_DEFAULTSTATE_BOOLEAN ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); @@ -1722,6 +1724,7 @@ void AxOptionButtonModel::convertFromProperties( PropertySet& rPropSet, const Co ControlConverter::convertToAxVisualEffect( rPropSet, mnSpecialEffect ); ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); // need to process the image if one exists ControlConverter::convertToAxState( rPropSet, maValue, mnMultiSelect, API_DEFAULTSTATE_BOOLEAN ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); @@ -1800,6 +1803,7 @@ void AxTextBoxModel::convertFromProperties( PropertySet& rPropSet, const Control setFlag( mnScrollBars, AX_SCROLLBAR_VERTICAL, bRes ); ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor, 0x80000005L ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); ControlConverter::convertToAxBorder( rPropSet, mnBorderColor, mnBorderStyle, mnSpecialEffect ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); @@ -1862,6 +1866,7 @@ void AxNumericFieldModel::convertFromProperties( PropertySet& rPropSet, const Co setFlag( mnScrollBars, AX_SCROLLBAR_VERTICAL, bRes ); ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); ControlConverter::convertToAxBorder( rPropSet, mnBorderColor, mnBorderStyle, mnSpecialEffect ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); @@ -1919,6 +1924,7 @@ void AxListBoxModel::convertFromProperties( PropertySet& rPropSet, const Control ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); ControlConverter::convertToAxBorder( rPropSet, mnBorderColor, mnBorderStyle, mnSpecialEffect ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); } @@ -2004,6 +2010,7 @@ void AxComboBoxModel::convertFromProperties( PropertySet& rPropSet, const Contro mnListRows = 1; } ControlConverter::convertToMSColor( rPropSet, PROP_BackgroundColor, mnBackColor ); + ControlConverter::convertToMSColor( rPropSet, PROP_TextColor, mnTextColor ); ControlConverter::convertToAxBorder( rPropSet, mnBorderColor, mnBorderStyle, mnSpecialEffect ); AxMorphDataModelBase::convertFromProperties( rPropSet, rConv ); commit e97590d3abd430d353cc692124bc41d0111e6cd4 Author: Ashod Nakashian <[email protected]> Date: Mon Dec 25 15:02:41 2017 -0500 rtl: support start/stop threads around pre-init This is necessary to avoid having extra threads while forking. After forking, the second stage of pre-init is started and so we start the stopped rtl threads. The comment for rtl_alloc_preInit_phase_t has more details. Reviewed-on: https://gerrit.libreoffice.org/47060 Tested-by: Jenkins <[email protected]> Reviewed-by: Ashod Nakashian <[email protected]> (cherry picked from commit 271a663d2f098f3f665cab6da2e13b265a7eab93) Change-Id: I1a3f7be74d4b04d0b2fc4a72b02124c2faa3c047 diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index f87caa5b0787..f8aebcfc8606 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3552,7 +3552,9 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char return 1; if (eStage == PRE_INIT) - rtl_alloc_preInit(true); + rtl_alloc_preInit(rtlAllocPreInitStart); + else if (eStage == SECOND_INIT) + rtl_alloc_preInit(rtlAllocPreInitEnd); if (eStage != SECOND_INIT) comphelper::LibreOfficeKit::setActive(); @@ -3707,7 +3709,7 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char } if (eStage == PRE_INIT) - rtl_alloc_preInit(false); + rtl_alloc_preInit(rtlAllocPostInit); return bInitialized; } diff --git a/include/rtl/alloc.h b/include/rtl/alloc.h index cb4f09cbb67c..83babccb9e70 100644 --- a/include/rtl/alloc.h +++ b/include/rtl/alloc.h @@ -289,15 +289,49 @@ SAL_DLLPUBLIC void SAL_CALL rtl_cache_free ( #ifdef LIBO_INTERNAL_ONLY /** @cond INTERNAL */ +/** rtl_alloc_preInit_phase_t + * + * This is used to control the pre-init logic + * in rtl_alloc_preInit. The reason for this is + * to first initialize all caching and other memory + * logic from WSD (the Online demaon) at startup. + * All these pages will then be forked over when + * spawning per-document instances. This is done + * by calling rtl_alloc_preInit with rtlAllocPreInitStart. + * + * However before forking we need to wind down + * all threads, which is required by design. + * This is done by calling rtl_alloc_preInit + * with rtlAllocPreInitEnd. + * + * And of course the stopped threads need restarting + * after forking to ensure correct cleanup of the + * caches and other memory allocations. This is done + * by calling rtl_alloc_preInit with rtlAllocPostInit. + * + * @since LibreOffice 6.1 + */ +typedef enum +{ + // Start phase I of pre-init. + rtlAllocPreInitStart, + // Finish phase I of pre-init (before forking). + rtlAllocPreInitEnd, + // Post pre-init and after forking. + rtlAllocPostInit + +} rtl_alloc_preInit_phase_t; + +/** @cond INTERNAL */ /** rtl_alloc_preInit * * This function, is called at the beginning and again * at the end of LibreOfficeKit pre-initialization to enable * various optimizations. * - * Its function is to annotate a section @start = true to - * end (@start = false) via. two calls. Inside this section - * string allocators are replaced with ones which cause the + * Its function is to annotate a section @phase = rtlAllocPreInitStart + * to end (@phase = rtlAllocPreInitEnd) via. two calls. Inside this + * section string allocators are replaced with ones which cause the * strings to be staticized at the end of the section. * * This brings a number of constraints - in particular no @@ -317,7 +351,7 @@ SAL_DLLPUBLIC void SAL_CALL rtl_cache_free ( * @since LibreOffice 6.1 */ SAL_DLLPUBLIC void SAL_CALL rtl_alloc_preInit ( - sal_Bool start + rtl_alloc_preInit_phase_t phase ) SAL_THROW_EXTERN_C(); /** @endcond */ diff --git a/sal/inc/rtllifecycle.h b/sal/inc/rtllifecycle.h index 82e38dee6372..528f4cc48a2f 100644 --- a/sal/inc/rtllifecycle.h +++ b/sal/inc/rtllifecycle.h @@ -26,6 +26,10 @@ void rtl_cache_fini(void); void ensureCacheSingleton(void); +void rtl_cache_stop_threads(void); + +void rtl_cache_start_threads(void); + void rtl_memory_init(void); void rtl_memory_fini(void); diff --git a/sal/qa/rtl/alloc/rtl_alloc.cxx b/sal/qa/rtl/alloc/rtl_alloc.cxx index 0e9b7c0f47a8..37c7b41eb338 100644 --- a/sal/qa/rtl/alloc/rtl_alloc.cxx +++ b/sal/qa/rtl/alloc/rtl_alloc.cxx @@ -158,7 +158,7 @@ public: const char *sample = "Hello World"; std::vector<OUString> aStrings; - rtl_alloc_preInit(true); + rtl_alloc_preInit(rtlAllocPreInitStart); OUString aFoo("foo"); @@ -183,7 +183,7 @@ public: } // should static-ize all the strings. - rtl_alloc_preInit(false); + rtl_alloc_preInit(rtlAllocPreInitEnd); for (size_t i = 0; i < aStrings.size(); ++i) CPPUNIT_ASSERT_MESSAGE( "static after.", (aStrings[i].pData->refCount & SAL_STRING_STATIC_FLAG) ); diff --git a/sal/rtl/alloc_cache.cxx b/sal/rtl/alloc_cache.cxx index 468bbdcdbf04..5ad8690e3152 100644 --- a/sal/rtl/alloc_cache.cxx +++ b/sal/rtl/alloc_cache.cxx @@ -1353,6 +1353,16 @@ rtl_cache_wsupdate_all(void * arg) #endif } +void rtl_cache_stop_threads(void) +{ + rtl_cache_wsupdate_fini(); +} + +void rtl_cache_start_threads(void) +{ + rtl_cache_wsupdate_init(); +} + void rtl_cache_init() { { diff --git a/sal/rtl/strimp.cxx b/sal/rtl/strimp.cxx index a739bda8f155..d520d2412b6e 100644 --- a/sal/rtl/strimp.cxx +++ b/sal/rtl/strimp.cxx @@ -21,6 +21,7 @@ #include <assert.h> #include <rtl/alloc.h> #include <rtl/ustring.h> +#include <rtllifecycle.h> #include "strimp.hxx" #include "alloc_impl.hxx" @@ -93,25 +94,45 @@ static void mark_static(void *addr, sal_Size /* size */, void *) str->refCount |= SAL_STRING_STATIC_FLAG; } -void SAL_CALL rtl_alloc_preInit (sal_Bool start) SAL_THROW_EXTERN_C() +void SAL_CALL rtl_alloc_preInit (rtl_alloc_preInit_phase_t phase) SAL_THROW_EXTERN_C() { - if (start) + switch (phase) { - rtl_allocateString = pre_allocateStringFn; - rtl_freeString = pre_freeStringFn; - pre_arena = rtl_arena_create("pre-init strings", 4, 0, - nullptr, rtl_arena_alloc, - rtl_arena_free, 0); - } - else // back to normal - { - rtl_arena_foreach(pre_arena, mark_static, nullptr); - rtl_allocateString = rtl_allocateMemory; - rtl_freeString = rtl_freeMemory; - - // TODO: also re-intialize main allocator as well. + case rtlAllocPreInitStart: + { + rtl_allocateString = pre_allocateStringFn; + rtl_freeString = pre_freeStringFn; + pre_arena = rtl_arena_create("pre-init strings", 4, 0, + nullptr, rtl_arena_alloc, + rtl_arena_free, 0); + + // To be consistent (and to ensure the rtl_cache threads are started). + ensureCacheSingleton(); + } + break; + + case rtlAllocPreInitEnd: + // back to normal + { + rtl_arena_foreach(pre_arena, mark_static, nullptr); + rtl_allocateString = rtl_allocateMemory; + rtl_freeString = rtl_freeMemory; + + // Stop the rtl cache thread to have no extra threads while forking. + rtl_cache_stop_threads(); + + // TODO: also re-initialize main allocator as well. + } + break; + + case rtlAllocPostInit: + { + // We have forked and need to restart threads and anything + // that must start after forking. + rtl_cache_start_threads(); + } + break; } } - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 6fb9ccd212130c890f93e27cf3a3b0743b42f45d Author: Tamas Bunth <[email protected]> Date: Wed Dec 27 20:25:33 2017 +0100 tdf#104734 Firebird: Add LONGVARBINARY/Image type Implement it as a user-defined Blob subtype. Change-Id: Ia369b6858e7d9191f34032445c1003931273e926 Reviewed-on: https://gerrit.libreoffice.org/47098 Reviewed-by: Tamás Bunth <[email protected]> Tested-by: Tamás Bunth <[email protected]> (cherry picked from commit 0217031a98508731f15df9d361a6e5b584db5716) diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index f18d903a7402..0015219d53eb 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -883,6 +883,11 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); + // Longvarbinary (SQL_BLOB) + // Distinguished from simple blob with a user-defined subtype. + aRow[2] = new ORowSetValueDecorator(DataType::LONGVARBINARY); + aResults.push_back(aRow); + // Integer Types common { aRow[6] = new ORowSetValueDecorator(); // Create Params diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index 53c388f4e01c..b41ea4e2d21b 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -10,6 +10,7 @@ #include "Table.hxx" #include "Tables.hxx" #include "Catalog.hxx" +#include "Util.hxx" #include <TConnection.hxx> @@ -113,6 +114,12 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP aSql.append(" "); aSql.append("SUB_TYPE 1"); } + else if(aType == DataType::LONGVARBINARY) + { + aSql.append(" "); + aSql.append("SUB_TYPE "); + aSql.append(OUString::number(static_cast<short>(BlobSubtype::Image))); + } } if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty()) diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx index 4036566b88dd..dd1213238d56 100644 --- a/connectivity/source/drivers/firebird/Util.cxx +++ b/connectivity/source/drivers/firebird/Util.cxx @@ -151,6 +151,8 @@ sal_Int32 firebird::ColumnTypeInfo::getSdbcType() const return DataType::BLOB; case BlobSubtype::Clob: return DataType::CLOB; + case BlobSubtype::Image: + return DataType::LONGVARBINARY; default: SAL_WARN("connectivity.firebird", "Unknown subtype for Blob type: " << aSubType); assert(!"Unknown subtype for Blob type"); // Should never happen diff --git a/connectivity/source/drivers/firebird/Util.hxx b/connectivity/source/drivers/firebird/Util.hxx index 2bf242ff441b..e93d3b68f288 100644 --- a/connectivity/source/drivers/firebird/Util.hxx +++ b/connectivity/source/drivers/firebird/Util.hxx @@ -28,9 +28,13 @@ namespace connectivity // Type Blob has 2 subtypes values // 0 for BLOB, 1 for CLOB // see http://www.firebirdfaq.org/faq48/ + // User-defined subtypes are negative. + // Use a number for image which is very unlikely to be defined by a + // user. enum class BlobSubtype { Blob = 0, - Clob = 1 + Clob = 1, + Image = -9546 }; // Numeric and decimal types can be identified by their subtype commit 2c05c3bd2876707286cc9aec1ff9b9fbfa8e1b69 Author: Tamas Bunth <[email protected]> Date: Thu Dec 28 11:53:24 2017 +0100 Firebird: use 32 bit Change-Id: I435524d1852a6691b382b93c9b6d2a7705938cd7 Reviewed-on: https://gerrit.libreoffice.org/47130 Reviewed-by: Tamás Bunth <[email protected]> Tested-by: Tamás Bunth <[email protected]> (cherry picked from commit 64d4f117447d990ed3215b0dd619e07de26ce417) diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index d1de5787ab85..f18d903a7402 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -874,7 +874,7 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() // Clob (SQL_BLOB) aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); // BLOB, with subtype 1 aRow[2] = new ORowSetValueDecorator(DataType::CLOB); - aRow[3] = new ORowSetValueDecorator(sal_Int16(2147483647)); // Precision = max length + aRow[3] = new ORowSetValueDecorator(sal_Int32(2147483647)); // Precision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( sal_Int16(ColumnSearch::FULL)); // Searchable commit d12526684a43477a7c600936c17c27d28effa1df Author: Tamas Bunth <[email protected]> Date: Wed Dec 13 13:46:39 2017 +0100 tdf#104734 Firebird improve XClob implementation Create a more effective implementation of XClob::length() and XClob::getSubString() methods, where string is read segment-by-segment instead of reading the whole underlying blob. That way it is possible to handle big texts which would not fit into memory. Also allow reading Clob data from a resultset with getString() and writing it in a prepared statement with setString(). Implement XPreparedStatement::setClob(). Also implement a private version of setClob() for creating a clob from OUString: Allow the creation of a clob column with GUI by adding a new type in ODataBaseMetaData::getTypeInfo(). Change-Id: Ibcbbdd80e8eed5e2a3fe55b0fa196401f1bcbcdf Reviewed-on: https://gerrit.libreoffice.org/47093 Reviewed-by: Tamás Bunth <[email protected]> Tested-by: Tamás Bunth <[email protected]> (cherry picked from commit f80b51ae441e3483a2e9b77a30b932d4e8fba192) diff --git a/connectivity/source/drivers/firebird/Blob.cxx b/connectivity/source/drivers/firebird/Blob.cxx index d7e3ac40f016..96e350d7a89b 100644 --- a/connectivity/source/drivers/firebird/Blob.cxx +++ b/connectivity/source/drivers/firebird/Blob.cxx @@ -70,9 +70,14 @@ void Blob::ensureBlobIsOpened() m_nBlobPosition = 0; char aBlobItems[] = { - isc_info_blob_total_length + isc_info_blob_total_length, + isc_info_blob_max_segment }; - char aResultBuffer[20]; + + // Assuming a data (e.g. legth of blob) is maximum 64 bit. + // That means we need 8 bytes for data + 2 for length of data + 1 for item + // identifier for each item. + char aResultBuffer[11 + 11]; aErr = isc_blob_info(m_statusVector, &m_blobHandle, @@ -84,17 +89,63 @@ void Blob::ensureBlobIsOpened() if (aErr) evaluateStatusVector(m_statusVector, "isc_blob_info", *this); - if (*aResultBuffer == isc_info_blob_total_length) + char* pIt = aResultBuffer; + while( *pIt != isc_info_end ) // info is in clusters { - short aResultLength = (short) isc_vax_integer(aResultBuffer+1, 2); - m_nBlobLength = isc_vax_integer(aResultBuffer+3, aResultLength); + char item = *pIt++; + short aResultLength = (short) isc_vax_integer(pIt, 2); + + pIt += 2; + switch(item) + { + case isc_info_blob_total_length: + m_nBlobLength = isc_vax_integer(pIt, aResultLength); + break; + case isc_info_blob_max_segment: + m_nMaxSegmentSize = isc_vax_integer(pIt, aResultLength); + break; + default: + assert(false); + break; + } + pIt += aResultLength; } - else +} + +sal_uInt16 Blob::getMaximumSegmentSize() +{ + ensureBlobIsOpened(); + + return m_nMaxSegmentSize; +} + +bool Blob::readOneSegment(uno::Sequence< sal_Int8 >& rDataOut) +{ + checkDisposed(Blob_BASE::rBHelper.bDisposed); + ensureBlobIsOpened(); + + sal_uInt16 nMaxSize = getMaximumSegmentSize(); + + if(rDataOut.getLength() < nMaxSize) + rDataOut.realloc(nMaxSize); + + sal_uInt16 nActualSize = 0; + ISC_STATUS aRet = isc_get_segment(m_statusVector, + &m_blobHandle, + &nActualSize, + nMaxSize, + reinterpret_cast<char*>(rDataOut.getArray()) ); + + if (aRet && aRet != isc_segstr_eof && IndicatesError(m_statusVector)) { - assert(false); + OUString sError(StatusVectorToString(m_statusVector, "isc_get_segment")); + throw IOException(sError, *this); } + m_nBlobPosition += nActualSize; + return aRet == isc_segstr_eof; // last segment read } + void Blob::closeBlob() { MutexGuard aGuard(m_aMutex); diff --git a/connectivity/source/drivers/firebird/Blob.hxx b/connectivity/source/drivers/firebird/Blob.hxx index 9afa09dec8fd..0a3627de417c 100644 --- a/connectivity/source/drivers/firebird/Blob.hxx +++ b/connectivity/source/drivers/firebird/Blob.hxx @@ -41,6 +41,7 @@ namespace connectivity bool m_bBlobOpened; sal_Int64 m_nBlobLength; + sal_uInt16 m_nMaxSegmentSize; sal_Int64 m_nBlobPosition; ISC_STATUS_ARRAY m_statusVector; @@ -54,12 +55,15 @@ namespace connectivity * @throws css::sdbc::SQLException */ void closeBlob(); + sal_uInt16 getMaximumSegmentSize(); public: Blob(isc_db_handle* pDatabaseHandle, isc_tr_handle* pTransactionHandle, ISC_QUAD const & aBlobID); + bool readOneSegment(css::uno::Sequence< sal_Int8 >& rDataOut); + // ---- XBlob ---------------------------------------------------- virtual sal_Int64 SAL_CALL length() override; diff --git a/connectivity/source/drivers/firebird/Clob.cxx b/connectivity/source/drivers/firebird/Clob.cxx index 7e2d49727ed1..d14e35723569 100644 --- a/connectivity/source/drivers/firebird/Clob.cxx +++ b/connectivity/source/drivers/firebird/Clob.cxx @@ -28,7 +28,8 @@ Clob::Clob(isc_db_handle* pDatabaseHandle, isc_tr_handle* pTransactionHandle, ISC_QUAD const & aBlobID): Clob_BASE(m_aMutex), - m_aBlob(new connectivity::firebird::Blob(pDatabaseHandle, pTransactionHandle, aBlobID)) + m_aBlob(new connectivity::firebird::Blob(pDatabaseHandle, pTransactionHandle, aBlobID)), + m_nCharCount(-1) { } @@ -44,13 +45,27 @@ sal_Int64 SAL_CALL Clob::length() MutexGuard aGuard(m_aMutex); checkDisposed(Clob_BASE::rBHelper.bDisposed); - // read the entire blob - // TODO FIXME better solution? - uno::Sequence < sal_Int8 > aEntireBlob = m_aBlob->getBytes( 1, m_aBlob->length()); - OUString sEntireClob ( reinterpret_cast< sal_Char *>( aEntireBlob.getArray() ), - aEntireBlob.getLength(), + if( m_nCharCount >= 0 ) + return m_nCharCount; + m_nCharCount = 0; + + // Read each segment, and calculate it's size by interpreting it as a + // character stream. Assume that no characters are split by the segments. + bool bLastSegmRead = false; + do + { + uno::Sequence < sal_Int8 > aSegmentBytes; + bLastSegmRead = m_aBlob->readOneSegment( aSegmentBytes ); + OUString sSegment ( reinterpret_cast< sal_Char *>( aSegmentBytes.getArray() ), + aSegmentBytes.getLength(), RTL_TEXTENCODING_UTF8 ); - return sEntireClob.getLength(); + + if( !bLastSegmRead) + m_nCharCount += sSegment.getLength(); + }while( !bLastSegmRead ); + + m_aBlob->closeInput(); // reset position + return m_nCharCount; } OUString SAL_CALL Clob::getSubString(sal_Int64 nPosition, @@ -58,19 +73,58 @@ OUString SAL_CALL Clob::getSubString(sal_Int64 nPosition, { MutexGuard aGuard(m_aMutex); checkDisposed(Clob_BASE::rBHelper.bDisposed); - - // read the entire blob - // TODO FIXME better solution? - // TODO FIXME Assume indexing of nPosition starts at position 1. - uno::Sequence < sal_Int8 > aEntireBlob = m_aBlob->getBytes( 1, m_aBlob->length()); - OUString sEntireClob ( reinterpret_cast< sal_Char *>( aEntireBlob.getArray() ), - aEntireBlob.getLength(), + // TODO do not reset position if it is not necessary + m_aBlob->closeInput(); // reset position + + OUStringBuffer sSegmentBuffer; + sal_Int64 nActPos = 1; + sal_Int32 nActLen = 0; + + // skip irrelevant parts + while( nActPos < nPosition ) + { + uno::Sequence < sal_Int8 > aSegmentBytes; + bool bLastRead = m_aBlob->readOneSegment( aSegmentBytes ); + if( bLastRead ) + throw lang::IllegalArgumentException("nPosition out of range", *this, 0); + + OUString sSegment ( reinterpret_cast< sal_Char *>( aSegmentBytes.getArray() ), + aSegmentBytes.getLength(), RTL_TEXTENCODING_UTF8 ); - - if( nPosition + nLength - 1 > sEntireClob.getLength() ) - throw lang::IllegalArgumentException("nPosition out of range", *this, 0); - - return sEntireClob.copy(nPosition - 1 , nLength); + sal_Int32 nStrLen = sSegment.getLength(); + nActPos += nStrLen; + if( nActPos > nPosition ) + { + sal_Int32 nCharsToCopy = static_cast<sal_Int32>(nActPos - nPosition); + if( nCharsToCopy > nLength ) + nCharsToCopy = nLength; + // append relevant part of first segment + sSegmentBuffer.append( sSegment.copy(0, nCharsToCopy ) ); + nActLen += sSegmentBuffer.getLength(); + } + } + + // read nLength characters + while( nActLen < nLength ) + { + uno::Sequence < sal_Int8 > aSegmentBytes; + bool bLastRead = m_aBlob->readOneSegment( aSegmentBytes ); + + OUString sSegment ( reinterpret_cast< sal_Char *>( aSegmentBytes.getArray() ), + aSegmentBytes.getLength(), + RTL_TEXTENCODING_UTF8 ); + sal_Int32 nStrLen = sSegment.getLength(); + if( nActLen + nStrLen > nLength ) + sSegmentBuffer.append(sSegment.copy(0, nLength - nActLen) ); + else + sSegmentBuffer.append(sSegment); + nActLen += nStrLen; + + if( bLastRead && nActLen < nLength ) + throw lang::IllegalArgumentException("out of range", *this, 0); + } + + return sSegmentBuffer.makeStringAndClear(); } uno::Reference< XInputStream > SAL_CALL Clob::getCharacterStream() diff --git a/connectivity/source/drivers/firebird/Clob.hxx b/connectivity/source/drivers/firebird/Clob.hxx index d435312f9f36..738b0ce86c64 100644 --- a/connectivity/source/drivers/firebird/Clob.hxx +++ b/connectivity/source/drivers/firebird/Clob.hxx @@ -38,6 +38,8 @@ namespace connectivity */ rtl::Reference<connectivity::firebird::Blob> m_aBlob; + sal_Int64 m_nCharCount; + public: Clob(isc_db_handle* pDatabaseHandle, isc_tr_handle* pTransactionHandle, diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index 614ccf7c2409..d1de5787ab85 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -870,6 +870,15 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[9] = new ORowSetValueDecorator( sal_Int16(ColumnSearch::NONE)); // Searchable + + // Clob (SQL_BLOB) + aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); // BLOB, with subtype 1 + aRow[2] = new ORowSetValueDecorator(DataType::CLOB); + aRow[3] = new ORowSetValueDecorator(sal_Int16(2147483647)); // Precision = max length + aRow[6] = new ORowSetValueDecorator(); // Create Params + aRow[9] = new ORowSetValueDecorator( + sal_Int16(ColumnSearch::FULL)); // Searchable + aRow[12] = new ORowSetValueDecorator(false); // Autoincrement aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index 37441d5c6b1f..afe1fa3229a6 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.cxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx @@ -178,10 +178,10 @@ void SAL_CALL OPreparedStatement::disposing() } void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, - const OUString& x) + const OUString& sInput) { SAL_INFO("connectivity.firebird", - "setString(" << nParameterIndex << " , " << x << ")"); + "setString(" << nParameterIndex << " , " << sInput << ")"); MutexGuard aGuard( m_aMutex ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); @@ -190,7 +190,7 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, checkParameterIndex(nParameterIndex); setParameterNull(nParameterIndex, false); - OString str = OUStringToOString(x , RTL_TEXTENCODING_UTF8 ); + OString str = OUStringToOString(sInput , RTL_TEXTENCODING_UTF8 ); XSQLVAR* pVar = m_pInSqlda->sqlvar + (nParameterIndex - 1); @@ -219,6 +219,10 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, // Fill remainder with spaces memset(pVar->sqldata + str.getLength(), ' ', pVar->sqllen - str.getLength()); break; + case SQL_BLOB: // Clob + assert( pVar->sqlsubtype == static_cast<short>(BlobSubtype::Clob) ); + setClob(nParameterIndex, sInput ); + break; default: ::dbtools::throwSQLException( "Incorrect type for setString", @@ -506,21 +510,105 @@ void OPreparedStatement::closeBlobAfterWriting(isc_blob_handle& rBlobHandle) ISC_STATUS aErr; aErr = isc_close_blob(m_statusVector, - &rBlobHandle); + &rBlobHandle); if (aErr) { evaluateStatusVector(m_statusVector, - "isc_close_blob failed", - *this); + "isc_close_blob failed", + *this); + assert(false); + } +} + +void SAL_CALL OPreparedStatement::setClob(sal_Int32 nParameterIndex, const Reference< XClob >& xClob ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); + +#if SAL_TYPES_SIZEOFPOINTER == 8 + isc_blob_handle aBlobHandle = 0; +#else + isc_blob_handle aBlobHandle = nullptr; +#endif + ISC_QUAD aBlobId; + + openBlobForWriting(aBlobHandle, aBlobId); + + + // Max segment size is 2^16 == SAL_MAX_UINT16 + // SAL_MAX_UINT16 / 4 is surely enough for UTF-8 + // TODO apply max segment size to character encoding + sal_Int64 nCharWritten = 1; // XClob is indexed from 1 + ISC_STATUS aErr = 0; + sal_Int64 nLen = xClob->length(); + while ( nLen > nCharWritten ) + { + sal_Int64 nCharRemain = nLen - nCharWritten; + constexpr sal_uInt16 MAX_SIZE = SAL_MAX_UINT16 / 4; + sal_uInt16 nWriteSize = (nCharRemain > MAX_SIZE) ? MAX_SIZE : nCharRemain; + OString sData = OUStringToOString( + xClob->getSubString(nCharWritten, nWriteSize), + RTL_TEXTENCODING_UTF8); + aErr = isc_put_segment( m_statusVector, + &aBlobHandle, + sData.getLength(), + sData.getStr() ); + nCharWritten += nWriteSize; + + if (aErr) + break; + } + + // We need to make sure we close the Blob even if their are errors, hence evaluate + // errors after closing. + closeBlobAfterWriting(aBlobHandle); + + if (aErr) + { + evaluateStatusVector(m_statusVector, + "isc_put_segment failed", + *this); assert(false); } + + setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB); } -void SAL_CALL OPreparedStatement::setClob( sal_Int32, const Reference< XClob >& ) +void OPreparedStatement::setClob( sal_Int32 nParameterIndex, const OUString& rStr ) { ::osl::MutexGuard aGuard( m_aMutex ); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); +#if SAL_TYPES_SIZEOFPOINTER == 8 + isc_blob_handle aBlobHandle = 0; +#else + isc_blob_handle aBlobHandle = nullptr; +#endif + ISC_QUAD aBlobId; + + openBlobForWriting(aBlobHandle, aBlobId); + + OString sData = OUStringToOString( + rStr, + RTL_TEXTENCODING_UTF8); + ISC_STATUS aErr = isc_put_segment( m_statusVector, + &aBlobHandle, + sData.getLength(), + sData.getStr() ); + + // We need to make sure we close the Blob even if their are errors, hence evaluate + // errors after closing. + closeBlobAfterWriting(aBlobHandle); + + if (aErr) + { + evaluateStatusVector(m_statusVector, + "isc_put_segment failed", + *this); + assert(false); + } + + setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB); } void SAL_CALL OPreparedStatement::setBlob(sal_Int32 nParameterIndex, diff --git a/connectivity/source/drivers/firebird/PreparedStatement.hxx b/connectivity/source/drivers/firebird/PreparedStatement.hxx index 81910ad1f3dd..19f19d423c7b 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.hxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.hxx @@ -78,6 +78,7 @@ namespace connectivity * Assumes that all necessary mutexes have been taken. */ void closeBlobAfterWriting(isc_blob_handle& rBlobHandle); + void setClob(sal_Int32 nParamIndex, const OUString& rStr); protected: virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, diff --git a/connectivity/source/drivers/firebird/ResultSet.cxx b/connectivity/source/drivers/firebird/ResultSet.cxx index abb0c03b8be0..9e8387d39a3d 100644 --- a/connectivity/source/drivers/firebird/ResultSet.cxx +++ b/connectivity/source/drivers/firebird/ResultSet.cxx @@ -604,6 +604,11 @@ OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT return OUString(); // never reached } } + else if(aSqlType == SQL_BLOB && aSqlSubType == static_cast<short>(BlobSubtype::Clob) ) + { + uno::Reference<XClob> xClob = getClob(nColumnIndex); + return xClob->getSubString( 0, xClob->length() ); + } else { return retrieveValue< ORowSetValue >(nColumnIndex, 0); diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index 57a44650589e..53c388f4e01c 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -106,6 +106,13 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP aSql.append(" "); aSql.append("CHARACTER SET OCTETS"); } + else if(aType == DataType::CLOB) + { + // CLOB is a special type of blob in Firebird context. + // Subtype number 1 always refers to CLOB + aSql.append(" "); + aSql.append("SUB_TYPE 1"); + } } if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty()) diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx index e91e0da0bdf9..4036566b88dd 100644 --- a/connectivity/source/drivers/firebird/Util.cxx +++ b/connectivity/source/drivers/firebird/Util.cxx @@ -118,13 +118,14 @@ sal_Int32 firebird::ColumnTypeInfo::getSdbcType() const short aSubType = m_aSubType; if( m_nScale > 0 ) { - // scale makes sense only for decimal and numeric types - assert(aType == SQL_SHORT || aType == SQL_LONG || aType == SQL_DOUBLE - || aType == SQL_INT64); - - // if scale is set without subtype then imply numeric - if( static_cast<NumberSubType>(aSubType) == NumberSubType::Other ) - aSubType = static_cast<short>(NumberSubType::Numeric); + // numeric / decimal + if(aType == SQL_SHORT || aType == SQL_LONG || aType == SQL_DOUBLE + || aType == SQL_INT64) + { + // if scale is set without subtype then imply numeric + if( static_cast<NumberSubType>(aSubType) == NumberSubType::Other ) + aSubType = static_cast<short>(NumberSubType::Numeric); + } } switch (aType) commit d0f6e30ed05b3949436eb2d49f33bf8a30dc47ef Author: Tamas Bunth <[email protected]> Date: Mon Dec 18 14:47:40 2017 +0100 tdf#104734 Firebird: Add VARBINARY type to driver Change-Id: I9a1b3aa9bde855577078fe0db2e31a9c160031d7 Reviewed-on: https://gerrit.libreoffice.org/47092 Tested-by: Jenkins <[email protected]> Reviewed-by: Tamás Bunth <[email protected]> (cherry picked from commit e7a80ddb91c44711296aa996bf00242edbfba32d) diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index dcb617363692..614ccf7c2409 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -863,6 +863,17 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); + // Varbinary (VARCHAR) + aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); + aRow[2] = new ORowSetValueDecorator(DataType::VARBINARY); + aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length + aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params + aRow[9] = new ORowSetValueDecorator( + sal_Int16(ColumnSearch::NONE)); // Searchable + aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale + aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale + aResults.push_back(aRow); + // Integer Types common { aRow[6] = new ORowSetValueDecorator(); // Create Params diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx index 725ed288d00a..b598846545de 100644 --- a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx +++ b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx @@ -96,7 +96,8 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column) short aType = m_pSqlda->sqlvar[column-1].sqltype & ~1; OUString sCharset; - if(aType == SQL_TEXT) + // do not query the character set unnecessarily + if(aType == SQL_TEXT || aType == SQL_VARYING) { sCharset = getCharacterSet(column); } diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index 5a79f8afe33d..57a44650589e 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -101,7 +101,7 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP sal_Int32 aType = 0; xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= aType; - if(aType == DataType::BINARY) + if(aType == DataType::BINARY || aType == DataType::VARBINARY) { aSql.append(" "); aSql.append("CHARACTER SET OCTETS"); diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx index 20587e5172ba..e91e0da0bdf9 100644 --- a/connectivity/source/drivers/firebird/Util.cxx +++ b/connectivity/source/drivers/firebird/Util.cxx @@ -100,8 +100,11 @@ sal_Int32 lcl_getCharColumnType( short aType, const OUString& sCharset ) return DataType::BINARY; else return DataType::CHAR; - case SQL_VARYING: // TODO VARBINARY - return DataType::VARCHAR; + case SQL_VARYING: + if( sCharset == "OCTETS") + return DataType::VARBINARY; + else + return DataType::VARCHAR; default: assert(false); return 0; commit a50a418c946c5f37de9bc6ae5853744e71f78147 Author: Tamas Bunth <[email protected]> Date: Sat Dec 16 12:57:43 2017 +0100 tdf#104734 Firebird: Add Binary (fix) type There is no explicit binary type in Firebird. It can be accomplished using the CHAR type with a special character set, which tells the database that it is binary data and there is no collation. (called OCTETS). Because of that, we also need the character set to decide the exact column type. And also refactor some parts of the driver: - Create class to determine internal type from firebird type, subtype, scale and character set. - Use internal type (DataType::XXX) in XDatabaseMetaData::getTypeInfo() indirectly. (We want to return a Firebird type for each internal type, not in the opposite direction. Change-Id: Ica56a84d89253e11936e7012086fe1d9f61a65f0 Reviewed-on: https://gerrit.libreoffice.org/47091 Tested-by: Jenkins <[email protected]> Reviewed-by: Tamás Bunth <[email protected]> (cherry picked from commit bf662904c4b60e93c6b86e06288d41996eed12a2) diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx index 92e46c8ba95d..dcb617363692 100644 --- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx +++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx @@ -827,9 +827,9 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[17] = new ORowSetValueDecorator(); // Unused aRow[18] = new ORowSetValueDecorator(sal_Int16(10));// Radix - // SQL_TEXT + // Char aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TEXT, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::CHAR); aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -839,9 +839,9 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); - // SQL_VARYING + // Varchar aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_VARYING, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR); aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -851,6 +851,18 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); + // Binary (CHAR) + // It is distinguished from Text type by its character set + aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); + aRow[2] = new ORowSetValueDecorator(DataType::BINARY); + aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length + aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params + aRow[9] = new ORowSetValueDecorator( + sal_Int16(ColumnSearch::NONE)); // Searchable + aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale + aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale + aResults.push_back(aRow); + // Integer Types common { aRow[6] = new ORowSetValueDecorator(); // Create Params @@ -860,19 +872,19 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale } - // SQL_SHORT + // Smallint (SQL_SHORT) aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_SHORT, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::SMALLINT); aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision aResults.push_back(aRow); - // SQL_LONG + // Integer (SQL_LONG) aRow[1] = new ORowSetValueDecorator(OUString("INTEGER")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_LONG, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::INTEGER); aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision aResults.push_back(aRow); - // SQL_INT64 + // Bigint (SQL_INT64) aRow[1] = new ORowSetValueDecorator(OUString("BIGINT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_INT64, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::BIGINT); aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision aResults.push_back(aRow); @@ -884,14 +896,14 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() } aRow[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params - // NUMERIC + // Numeric aRow[1] = new ORowSetValueDecorator(OUString("NUMERIC")); aRow[2] = new ORowSetValueDecorator(DataType::NUMERIC); aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale aResults.push_back(aRow); - // DECIMAL + // Decimal aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL")); aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision @@ -900,34 +912,26 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aResults.push_back(aRow); aRow[6] = new ORowSetValueDecorator(); // Create Params - // SQL_FLOAT + // Float (SQL_FLOAT) aRow[1] = new ORowSetValueDecorator(OUString("FLOAT")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_FLOAT, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::FLOAT); aRow[3] = new ORowSetValueDecorator(sal_Int16(7)); // Precision aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale aResults.push_back(aRow); - // SQL_DOUBLE + // Double (SQL_DOUBLE) aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_DOUBLE, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE); aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale aResults.push_back(aRow); -// // SQL_D_FLOAT -// aRow[1] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(SQL_D_FLOAT, 0, 0)); -// aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_D_FLOAT, 0, 0)); -// aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision -// aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale -// aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale -// aResults.push_back(aRow); // TODO: no idea whether D_FLOAT corresponds to an sql type // SQL_TIMESTAMP - // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TIMESTAMP, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -938,9 +942,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aResults.push_back(aRow); // SQL_TYPE_TIME - // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("TIME")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_TIME, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::TIME); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -951,9 +954,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aResults.push_back(aRow); // SQL_TYPE_DATE - // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("DATE")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_TYPE_DATE, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::DATE); aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -964,9 +966,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aResults.push_back(aRow); // SQL_BLOB - // TODO: precision? aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BLOB, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::BLOB); aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -977,9 +978,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aResults.push_back(aRow); // SQL_BOOLEAN - // TODO FIXME precision aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN")); - aRow[2] = new ORowSetValueDecorator(getColumnTypeFromFBType(SQL_BOOLEAN, 0, 0)); + aRow[2] = new ORowSetValueDecorator(DataType::BOOLEAN); aRow[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length aRow[6] = new ORowSetValueDecorator(); // Create Params aRow[9] = new ORowSetValueDecorator( @@ -989,10 +989,6 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale aResults.push_back(aRow); - // TODO: complete -// case SQL_ARRAY: -// case SQL_NULL: -// case SQL_QUAD: // Is a "Blob ID" according to the docs } pResultSet->setRows(aResults); return xResultSet; @@ -1099,10 +1095,13 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( // this is also the one we manually fiddle when changin NULL/NOT NULL // (see Table.cxx) "relfields.RDB$NULL_FLAG, " // 11 - "fields.RDB$CHARACTER_LENGTH " // 12 + "fields.RDB$CHARACTER_LENGTH, " // 12 + "charset.RDB$CHARACTER_SET_NAME " // 13 "FROM RDB$RELATION_FIELDS relfields " "JOIN RDB$FIELDS fields " "on (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) " + "LEFT JOIN RDB$CHARACTER_SETS charset " + "on (fields.RDB$CHARACTER_SET_ID = charset.RDB$CHARACTER_SET_ID) " "WHERE (1 = 1) "); if (!tableNamePattern.isEmpty()) @@ -1152,11 +1151,16 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); // 5. Datatype short aType = getFBTypeFromBlrType(xRow->getShort(6)); - short aSubType = xRow->getShort(7); short aScale = xRow->getShort(10); - aCurrentRow[5] = new ORowSetValueDecorator(getColumnTypeFromFBType(aType, aSubType, aScale)); + OUString sCharsetName = xRow->getString(13); + // result field may be filled with spaces + sCharsetName = sCharsetName.trim(); + ColumnTypeInfo aInfo(aType, xRow->getShort(7), aScale, + xRow->getString(13)); + + aCurrentRow[5] = new ORowSetValueDecorator(aInfo.getSdbcType()); // 6. Typename (SQL_*) - aCurrentRow[6] = new ORowSetValueDecorator(getColumnTypeNameFromFBType(aType, aSubType, aScale)); + aCurrentRow[6] = new ORowSetValueDecorator(aInfo.getColumnTypeName()); // 7. Column Sizes { diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx index e5ba68a3bd72..725ed288d00a 100644 --- a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx +++ b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx @@ -39,6 +39,39 @@ OResultSetMetaData::~OResultSetMetaData() { } +OUString OResultSetMetaData::getCharacterSet( sal_Int32 nIndex ) +{ + OUString sTable = getTableName( nIndex ); + if( !sTable.isEmpty() ) + { + OUString sColumnName = getColumnName( nIndex ); + + OUString sSql = "SELECT charset.RDB$CHARACTER_SET_NAME " + "FROM RDB$CHARACTER_SETS charset " + "JOIN RDB$FIELDS fields " + "ON (fields.RDB$CHARACTER_SET_ID = charset.RDB$CHARACTER_SET_ID) " + "JOIN RDB$RELATION_FIELDS relfields " + "ON (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) " + "WHERE relfields.RDB$RELATION_NAME = '" + + escapeWith(sTable, '\'', '\'') + "' AND " + "relfields.RDB$FIELD_NAME = '"+ escapeWith(sColumnName, '\'', '\'') +"'"; + + Reference<XStatement> xStmt= m_pConnection->createStatement(); + + Reference<XResultSet> xRes = + xStmt->executeQuery(sSql); + Reference<XRow> xRow ( xRes, UNO_QUERY); + if(xRes->next()) + { + OUString sCharset = xRow->getString(1).trim(); + return sCharset; + } + } + return OUString(); + + +} + void OResultSetMetaData::verifyValidColumn(sal_Int32 column) { if (column>getColumnCount() || column < 1) @@ -60,11 +93,20 @@ sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column) { verifyValidColumn(column); - short aType = m_pSqlda->sqlvar[column-1].sqltype; - short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype; - short aScale = m_pSqlda->sqlvar[column-1].sqlscale; + short aType = m_pSqlda->sqlvar[column-1].sqltype & ~1; + OUString sCharset; + + if(aType == SQL_TEXT) + { + sCharset = getCharacterSet(column); + } + + ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype, + m_pSqlda->sqlvar[column-1].sqlsubtype, + m_pSqlda->sqlvar[column-1].sqlscale, + sCharset ); - return getColumnTypeFromFBType(aType, aSubType, aScale); + return aInfo.getSdbcType(); } sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32) @@ -109,11 +151,11 @@ OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column) { verifyValidColumn(column); - short aType = m_pSqlda->sqlvar[column-1].sqltype; - short aSubType = m_pSqlda->sqlvar[column-1].sqlsubtype; - short aScale = m_pSqlda->sqlvar[column-1].sqlscale; + ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype, + m_pSqlda->sqlvar[column-1].sqlsubtype, + m_pSqlda->sqlvar[column-1].sqlscale ); - return getColumnTypeNameFromFBType(aType, aSubType, aScale); + return aInfo.getColumnTypeName(); } OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column) diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.hxx b/connectivity/source/drivers/firebird/ResultSetMetaData.hxx index d6dffe0cd708..1b134a0628fd 100644 --- a/connectivity/source/drivers/firebird/ResultSetMetaData.hxx +++ b/connectivity/source/drivers/firebird/ResultSetMetaData.hxx @@ -45,6 +45,7 @@ namespace connectivity /// @throws css::sdbc::SQLException void verifyValidColumn(sal_Int32 column); + OUString getCharacterSet(sal_Int32 nIndex); public: // a constructor, which is required for returning objects: OResultSetMetaData(Connection* pConnection, diff --git a/connectivity/source/drivers/firebird/Tables.cxx b/connectivity/source/drivers/firebird/Tables.cxx index c78939cdc201..5a79f8afe33d 100644 --- a/connectivity/source/drivers/firebird/Tables.cxx +++ b/connectivity/source/drivers/firebird/Tables.cxx @@ -92,6 +92,21 @@ OUString Tables::createStandardColumnPart(const Reference< XPropertySet >& xColP aSql.append(dbtools::createStandardTypePart(xColProp, _xConnection)); + // Add character set for BINARY (fix) type: + // BINARY is distinguished from other CHAR types by its character set. + // Octets is a special character set for binary data. + if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex( + PROPERTY_ID_TYPE)) ) + { + sal_Int32 aType = 0; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) + >>= aType; + if(aType == DataType::BINARY) + { + aSql.append(" "); + aSql.append("CHARACTER SET OCTETS"); + } + } if ( bIsAutoIncrement && !sAutoIncrementValue.isEmpty()) { diff --git a/connectivity/source/drivers/firebird/Util.cxx b/connectivity/source/drivers/firebird/Util.cxx index e30a7a9b41f8..20587e5172ba 100644 --- a/connectivity/source/drivers/firebird/Util.cxx +++ b/connectivity/source/drivers/firebird/Util.cxx @@ -17,6 +17,8 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::uno; +using namespace firebird; + OUString firebird::sanitizeIdentifier(const OUString& rIdentifier) { OUString sRet = rIdentifier.trim(); @@ -64,41 +66,76 @@ void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY& rStatusVector, } } -sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short aScale) +sal_Int32 lcl_getNumberType( short aType, NumberSubType aSubType ) +{ + switch(aSubType) + { + case NumberSubType::Numeric: + return DataType::NUMERIC; + case NumberSubType::Decimal: + return DataType::DECIMAL; + default: + switch(aType) + { + case SQL_SHORT: + return DataType::SMALLINT; + case SQL_LONG: + return DataType::INTEGER; + case SQL_DOUBLE: + return DataType::DOUBLE; + case SQL_INT64: + return DataType::BIGINT; + default: + assert(false); // not a number + return 0; + } + } +} +sal_Int32 lcl_getCharColumnType( short aType, const OUString& sCharset ) +{ + switch(aType) + { + case SQL_TEXT: + if( sCharset == "OCTETS") + return DataType::BINARY; + else + return DataType::CHAR; + case SQL_VARYING: // TODO VARBINARY + return DataType::VARCHAR; + default: + assert(false); + return 0; + } +} + +sal_Int32 firebird::ColumnTypeInfo::getSdbcType() const { - aType &= ~1; // Remove last bit -- it is used to denote whether column + short aType = m_aType & ~1; // Remove last bit -- it is used to denote whether column // can store Null, not needed for type determination + short aSubType = m_aSubType; + if( m_nScale > 0 ) + { + // scale makes sense only for decimal and numeric types + assert(aType == SQL_SHORT || aType == SQL_LONG || aType == SQL_DOUBLE + || aType == SQL_INT64); - // if scale is set without subtype then imply numeric - if(aSubType == 0 && aScale < 0) - aSubType = 1; + // if scale is set without subtype then imply numeric + if( static_cast<NumberSubType>(aSubType) == NumberSubType::Other ) + aSubType = static_cast<short>(NumberSubType::Numeric); + } switch (aType) { case SQL_TEXT: - return DataType::CHAR; case SQL_VARYING: - return DataType::VARCHAR; + return lcl_getCharColumnType(aType, m_sCharsetName); case SQL_SHORT: - if(aSubType == 1) - return DataType::NUMERIC; - if(aSubType == 2) - return DataType::DECIMAL; - return DataType::SMALLINT; case SQL_LONG: - if(aSubType == 1) - return DataType::NUMERIC; - if(aSubType == 2) - return DataType::DECIMAL; - return DataType::INTEGER; + case SQL_DOUBLE: + case SQL_INT64: + return lcl_getNumberType(aType, static_cast<NumberSubType>(aSubType) ); case SQL_FLOAT: return DataType::FLOAT; - case SQL_DOUBLE: - if(aSubType == 1) - return DataType::NUMERIC; - if(aSubType == 2) - return DataType::DECIMAL; - return DataType::DOUBLE; case SQL_D_FLOAT: return DataType::DOUBLE; case SQL_TIMESTAMP: @@ -121,12 +158,6 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short a return DataType::TIME; case SQL_TYPE_DATE: return DataType::DATE; - case SQL_INT64: - if(aSubType == 1) - return DataType::NUMERIC; - if(aSubType == 2) - return DataType::DECIMAL; - return DataType::BIGINT; case SQL_NULL: return DataType::SQLNULL; case SQL_QUAD: // Is a "Blob ID" according to the docs @@ -139,68 +170,48 @@ sal_Int32 firebird::getColumnTypeFromFBType(short aType, short aSubType, short a } } -OUString firebird::getColumnTypeNameFromFBType(short aType, short aSubType, short aScale) +OUString firebird::ColumnTypeInfo::getColumnTypeName() const { - aType &= ~1; // Remove last bit -- it is used to denote whether column + short aType = m_aType & ~1; // Remove last bit -- it is used to denote whether column // can store Null, not needed for type determination - // if scale is set without subtype than imply numeric - if(aSubType == 0 && aScale < 0) - aSubType = 1; - - switch (aType) + switch (aType) { - case SQL_TEXT: - return OUString("SQL_TEXT"); - case SQL_VARYING: - return OUString("SQL_VARYING"); - case SQL_SHORT: - if(aSubType == 1) - return OUString("SQL_NUMERIC"); - if(aSubType == 2) - return OUString("SQL_DECIMAL"); - return OUString("SQL_SHORT"); - case SQL_LONG: - if(aSubType == 1) - return OUString("SQL_NUMERIC"); - if(aSubType == 2) - return OUString("SQL_DECIMAL"); - return OUString("SQL_LONG"); - case SQL_FLOAT: - return OUString("SQL_FLOAT"); - case SQL_DOUBLE: - if(aSubType == 1) - return OUString("SQL_NUMERIC"); - if(aSubType == 2) - return OUString("SQL_DECIMAL"); - return OUString("SQL_DOUBLE"); - case SQL_D_FLOAT: - return OUString("SQL_D_FLOAT"); - case SQL_TIMESTAMP: - return OUString("SQL_TIMESTAMP"); - case SQL_BLOB: - return OUString("SQL_BLOB"); - case SQL_ARRAY: - return OUString("SQL_ARRAY"); - case SQL_TYPE_TIME: - return OUString("SQL_TYPE_TIME"); - case SQL_TYPE_DATE: ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
