Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 113, column 13
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name TableController.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D DBACCESS_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/unixODBC/inc -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/dbaccess/inc -I /home/maarten/src/libreoffice/core/dbaccess/source/inc -I /home/maarten/src/libreoffice/core/dbaccess/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/YaccTarget/connectivity/source/parse -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx

/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <FieldDescriptions.hxx>
21#include "TEditControl.hxx"
22#include <TableController.hxx>
23#include <TableDesignView.hxx>
24#include <TableRow.hxx>
25#include <TypeInfo.hxx>
26#include <UITools.hxx>
27#include <browserids.hxx>
28#include <core_resource.hxx>
29#include <strings.hrc>
30#include <strings.hxx>
31#include <defaultobjectnamecheck.hxx>
32#include <dlgsave.hxx>
33#include <indexdialog.hxx>
34#include <sqlmessage.hxx>
35
36#include <com/sun/star/frame/XTitleChangeListener.hpp>
37#include <com/sun/star/sdb/CommandType.hpp>
38#include <com/sun/star/sdb/SQLContext.hpp>
39#include <com/sun/star/sdbc/ColumnValue.hpp>
40#include <com/sun/star/sdbc/SQLWarning.hpp>
41#include <com/sun/star/sdbcx/KeyType.hpp>
42#include <com/sun/star/sdbcx/XAlterTable.hpp>
43#include <com/sun/star/sdbcx/XAppend.hpp>
44#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
45#include <com/sun/star/sdbcx/XDrop.hpp>
46#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
47#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
48
49#include <comphelper/processfactory.hxx>
50#include <connectivity/dbexception.hxx>
51#include <connectivity/dbtools.hxx>
52#include <connectivity/dbmetadata.hxx>
53#include <cppuhelper/exc_hlp.hxx>
54#include <tools/diagnose_ex.h>
55#include <vcl/svapp.hxx>
56#include <vcl/weld.hxx>
57
58#include <algorithm>
59#include <functional>
60
61extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
62org_openoffice_comp_dbu_OTableDesign_get_implementation(
63 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
64{
65 return cppu::acquire(new ::dbaui::OTableController(context));
66}
67
68using namespace ::com::sun::star;
69using namespace ::com::sun::star::uno;
70using namespace ::com::sun::star::io;
71using namespace ::com::sun::star::beans;
72using namespace ::com::sun::star::frame;
73using namespace ::com::sun::star::lang;
74using namespace ::com::sun::star::container;
75using namespace ::com::sun::star::sdbcx;
76using namespace ::com::sun::star::sdbc;
77using namespace ::com::sun::star::sdb;
78using namespace ::com::sun::star::ui;
79using namespace ::com::sun::star::util;
80using namespace ::dbtools;
81using namespace ::dbaui;
82using namespace ::comphelper;
83
84// number of columns when creating it from scratch
85#define NEWCOLS128 128
86
87namespace
88{
89 void dropTable(const Reference<XNameAccess>& _rxTable,const OUString& _sTableName)
90 {
91 if ( _rxTable->hasByName(_sTableName) )
92 {
93 Reference<XDrop> xNameCont(_rxTable,UNO_QUERY);
94 OSL_ENSURE(xNameCont.is(),"No drop interface for tables!")do { if (true && (!(xNameCont.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "94" ": "), "%s", "No drop interface for tables!"); } } while
(false)
;
95 if ( xNameCont.is() )
96 xNameCont->dropByName(_sTableName);
97 }
98 }
99}
100
101OUString SAL_CALL OTableController::getImplementationName()
102{
103 return "org.openoffice.comp.dbu.OTableDesign";
104}
105
106Sequence< OUString> OTableController::getSupportedServiceNames()
107{
108 return { "com.sun.star.sdb.TableDesign" };
109}
110
111OTableController::OTableController(const Reference< XComponentContext >& _rM) : OTableController_BASE(_rM)
112 ,m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_DBFIELDTYPES" "\004" u8"Unknown;Text;Number;Date/Time;Date;Time;Yes/No;Currency;Memo;Counter;Image;Text (fix);Decimal;Binary (fix);Binary;BigInt;Double;Float;Real;Integer;Small Integer;Tiny Integer;SQL Null;Object;Distinct;Structure;Field;BLOB;CLOB;REF;OTHER;Bit (fix)"
) )
)
113 ,m_pTypeInfo()
114 ,m_bAllowAutoIncrementValue(false)
115 ,m_bNew(true)
116{
117
118 InvalidateAll();
119 m_pTypeInfo = std::make_shared<OTypeInfo>();
120 m_pTypeInfo->aUIName = m_sTypeNames.getToken(TYPE_OTHER, ';');
121}
122
123OTableController::~OTableController()
124{
125 m_aTypeInfoIndex.clear();
126 m_aTypeInfo.clear();
127
128}
129
130void OTableController::startTableListening()
131{
132 Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
133 if (xComponent.is())
134 xComponent->addEventListener(static_cast<XModifyListener*>(this));
135}
136
137void OTableController::stopTableListening()
138{
139 Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
140 if (xComponent.is())
141 xComponent->removeEventListener(static_cast<XModifyListener*>(this));
142}
143
144void OTableController::disposing()
145{
146 OTableController_BASE::disposing();
147 clearView();
148
149 m_vRowList.clear();
150}
151
152FeatureState OTableController::GetState(sal_uInt16 _nId) const
153{
154 FeatureState aReturn;
155 // disabled automatically
156
157 switch (_nId)
158 {
159 case ID_BROWSER_CLOSE(5000 + 621):
160 aReturn.bEnabled = true;
161 break;
162 case ID_BROWSER_EDITDOC(5000 + 1312):
163 aReturn.bChecked = isEditable();
164 aReturn.bEnabled = true;
165 break;
166 case ID_BROWSER_SAVEDOC(5000 + 505):
167 aReturn.bEnabled = isEditable() && std::any_of(m_vRowList.begin(),m_vRowList.end(),std::mem_fn(&OTableRow::isValid));
168 break;
169 case ID_BROWSER_SAVEASDOC(5000 + 502):
170 aReturn.bEnabled = isConnected() && isEditable();
171 if ( aReturn.bEnabled )
172 {
173 aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(),
174 std::mem_fn(&OTableRow::isValid));
175 }
176 break;
177
178 case ID_BROWSER_CUT(5000 + 710):
179 aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isCutAllowed();
180 break;
181 case ID_BROWSER_COPY(5000 + 711):
182 aReturn.bEnabled = getView() && static_cast<OTableDesignView*>(getView())->isCopyAllowed();
183 break;
184 case ID_BROWSER_PASTE(5000 + 712):
185 aReturn.bEnabled = isEditable() && getView() && static_cast<OTableDesignView*>(getView())->isPasteAllowed();
186 break;
187 case SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 0 )
:
188 aReturn.bEnabled =
189 ( ( ((!m_bNew && impl_isModified()) || impl_isModified())
190 || Reference< XIndexesSupplier >(m_xTable, UNO_QUERY).is()
191 )
192 && isConnected()
193 );
194 if ( aReturn.bEnabled )
195 {
196 aReturn.bEnabled = std::any_of(m_vRowList.begin(),m_vRowList.end(),
197 std::mem_fn(&OTableRow::isValid));
198 }
199 break;
200 default:
201 aReturn = OTableController_BASE::GetState(_nId);
202 }
203 return aReturn;
204}
205
206void OTableController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
207{
208 switch(_nId)
209 {
210 case ID_BROWSER_EDITDOC(5000 + 1312):
211 setEditable(!isEditable());
212 static_cast<OTableDesignView*>(getView())->setReadOnly(!isEditable());
213 InvalidateFeature(ID_BROWSER_SAVEDOC(5000 + 505));
214 InvalidateFeature(ID_BROWSER_PASTE(5000 + 712));
215 InvalidateFeature(SID_BROWSER_CLEAR_QUERY( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 44 )
);
216 break;
217 case ID_BROWSER_SAVEASDOC(5000 + 502):
218 doSaveDoc(true);
219 break;
220 case ID_BROWSER_SAVEDOC(5000 + 505):
221 static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->SaveCurRow();
222 doSaveDoc(false);
223 break;
224 case ID_BROWSER_CUT(5000 + 710):
225 static_cast<OTableDesignView*>(getView())->cut();
226 break;
227 case ID_BROWSER_COPY(5000 + 711):
228 static_cast<OTableDesignView*>(getView())->copy();
229 break;
230 case ID_BROWSER_PASTE(5000 + 712):
231 static_cast<OTableDesignView*>(getView())->paste();
232 break;
233 case SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 0 )
:
234 doEditIndexes();
235 break;
236 default:
237 OTableController_BASE::Execute(_nId,aArgs);
238 }
239 InvalidateFeature(_nId);
240}
241
242bool OTableController::doSaveDoc(bool _bSaveAs)
243{
244 if (!isConnected())
245 reconnect(true); // ask the user for a new connection
246 Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
247
248 if (!xTablesSup.is())
249 {
250 OUString aMessage(DBA_RES(STR_TABLEDESIGN_CONNECTION_MISSING)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_CONNECTION_MISSING" "\004" u8"The table could not be saved due to problems connecting to the database."
) )
);
251 OSQLWarningBox aWarning(getFrameWeld(), aMessage);
252 aWarning.run();
253 return false;
254 }
255
256 // check if a column exists
257 // TODO
258
259 Reference<XNameAccess> xTables;
260 OUString sCatalog, sSchema;
261
262 bool bNew = m_sName.isEmpty();
263 bNew = bNew || m_bNew || _bSaveAs;
264
265 try
266 {
267 xTables = xTablesSup->getTables();
268 OSL_ENSURE(xTables.is(),"The tables can't be null!")do { if (true && (!(xTables.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "268" ": "), "%s", "The tables can't be null!"); } } while
(false)
;
269 bNew = bNew || (xTables.is() && !xTables->hasByName(m_sName));
270
271 // first we need a name for our query so ask the user
272 if(bNew)
273 {
274 OUString aName = DBA_RES(STR_TBL_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TBL_TITLE" "\004" u8"Table #") )
;
275 OUString aDefaultName = aName.getToken(0,' ');
276 aDefaultName = ::dbtools::createUniqueName(xTables,aDefaultName);
277
278 DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::TABLE );
279 OSaveAsDlg aDlg(getFrameWeld(), CommandType::TABLE, getORB(), getConnection(), aDefaultName, aNameChecker, SADFlags::NONE);
280 if (aDlg.run() != RET_OK)
281 return false;
282
283 m_sName = aDlg.getName();
284 sCatalog = aDlg.getCatalog();
285 sSchema = aDlg.getSchema();
286 }
287
288 // did we get a name
289 if(m_sName.isEmpty())
290 return false;
291 }
292 catch(Exception&)
293 {
294 OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "294" ": "), "%s", "OTableController::doSaveDoc: nothing is expected to happen here!"
); } } while (false)
;
295 }
296
297 bool bAlter = false;
298 bool bError = false;
299 SQLExceptionInfo aInfo;
300 try
301 {
302 // check the columns for double names
303 if(!checkColumns(bNew || !xTables->hasByName(m_sName)))
304 {
305 return false;
306 }
307
308 Reference<XPropertySet> xTable;
309 if(bNew || !xTables->hasByName(m_sName)) // just to make sure the table already exists
310 {
311 dropTable(xTables,m_sName);
312
313 Reference<XDataDescriptorFactory> xFact(xTables,UNO_QUERY);
314 OSL_ENSURE(xFact.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!")do { if (true && (!(xFact.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "314" ": "), "%s", "OTableController::doSaveDoc: No XDataDescriptorFactory available!"
); } } while (false)
;
315 xTable = xFact->createDataDescriptor();
316 OSL_ENSURE(xTable.is(),"OTableController::doSaveDoc: Create query failed!")do { if (true && (!(xTable.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "316" ": "), "%s", "OTableController::doSaveDoc: Create query failed!"
); } } while (false)
;
317 // to set the name is only allowed when the query is new
318 xTable->setPropertyValue(PROPERTY_CATALOGNAME"CatalogName",makeAny(sCatalog));
319 xTable->setPropertyValue(PROPERTY_SCHEMANAME"SchemaName",makeAny(sSchema));
320 xTable->setPropertyValue(PROPERTY_NAME"Name",makeAny(m_sName));
321
322 // now append the columns
323 Reference<XColumnsSupplier> xColSup(xTable,UNO_QUERY);
324 appendColumns(xColSup,bNew);
325 // now append the primary key
326 Reference<XKeysSupplier> xKeySup(xTable,UNO_QUERY);
327 appendPrimaryKey(xKeySup,bNew);
328 }
329 // now set the properties
330 if(bNew)
331 {
332 Reference<XAppend> xAppend(xTables,UNO_QUERY);
333 OSL_ENSURE(xAppend.is(),"OTableController::doSaveDoc: No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "333" ": "), "%s", "OTableController::doSaveDoc: No XAppend Interface!"
); } } while (false)
;
334 xAppend->appendByDescriptor(xTable);
335
336 assignTable();
337 if(!m_xTable.is()) // correct name and try again
338 {
339 // it can be that someone inserted new data for us
340 m_sName = ::dbtools::composeTableName( getConnection()->getMetaData(), xTable, ::dbtools::EComposeRule::InDataManipulation, false );
341 assignTable();
342 }
343 // now check if our datasource has set a tablefilter and if append the new table name to it
344 ::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld()); // we are not interested in the return value
345 Reference< frame::XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
346 if ( xEventListener.is() )
347 {
348 frame::TitleChangedEvent aEvent;
349 xEventListener->titleChanged(aEvent);
350 }
351 releaseNumberForComponent();
352 }
353 else if(m_xTable.is())
354 {
355 bAlter = true;
356 alterColumns();
357 }
358 reSyncRows();
359 }
360 catch(const SQLContext& e)
361 {
362 aInfo = SQLExceptionInfo(e);
363 }
364 catch(const SQLWarning& e)
365 {
366 aInfo = SQLExceptionInfo(e);
367 }
368 catch(const SQLException& e)
369 {
370 aInfo = SQLExceptionInfo(e);
371 }
372 catch(const ElementExistException& )
373 {
374 OUString sText( DBA_RES( STR_NAME_ALREADY_EXISTS )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_NAME_ALREADY_EXISTS" "\004" u8"The name \"#\" already exists."
) )
);
375 sText = sText.replaceFirst( "#" , m_sName);
376 OSQLMessageBox aDlg(getFrameWeld(), DBA_RES( STR_ERROR_DURING_CREATION )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_ERROR_DURING_CREATION" "\004" u8"Error during creation"
) )
, sText, MessBoxStyle::Ok, MessageType::Error);
377 aDlg.run();
378 bError = true;
379 }
380 catch( const Exception& )
381 {
382 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "382" ": ", "dbaccess" );
;
383 bError = true;
384 }
385
386 if ( aInfo.isValid() )
387 aInfo.prepend( DBA_RES( STR_TABLEDESIGN_SAVE_ERROR )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_SAVE_ERROR" "\004" u8"Error while saving the table design"
) )
);
388 showError(aInfo);
389
390 if (aInfo.isValid() || bError)
391 {
392 if(!bAlter || bNew)
393 {
394 m_sName.clear();
395 stopTableListening();
396 m_xTable = nullptr;
397 }
398 }
399 return ! (aInfo.isValid() || bError);
400}
401
402void OTableController::doEditIndexes()
403{
404 // table needs to be saved before editing indexes
405 if (m_bNew || isModified())
406 {
407 std::unique_ptr<weld::MessageDialog> xAsk(Application::CreateMessageDialog(getFrameWeld(),
408 VclMessageType::Question, VclButtonsType::YesNo,
409 DBA_RES(STR_QUERY_SAVE_TABLE_EDIT_INDEXES)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_QUERY_SAVE_TABLE_EDIT_INDEXES" "\004" u8"Before you can edit the indexes of a table, you have to save it.\nDo you want to save the changes now?"
) )
));
410 if (RET_YES != xAsk->run())
411 return;
412
413 if (!doSaveDoc(false))
414 return;
415
416 OSL_ENSURE(!m_bNew && !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?")do { if (true && (!(!m_bNew && !isModified())
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "416" ": "), "%s", "OTableController::doEditIndexes: what the hell did doSaveDoc do?"
); } } while (false)
;
417 }
418
419 Reference< XNameAccess > xIndexes; // will be the keys of the table
420 Sequence< OUString > aFieldNames; // will be the column names of the table
421 try
422 {
423 // get the keys
424 Reference< XIndexesSupplier > xIndexesSupp(m_xTable, UNO_QUERY);
425 if (xIndexesSupp.is())
426 {
427 xIndexes = xIndexesSupp->getIndexes();
428 OSL_ENSURE(xIndexes.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!")do { if (true && (!(xIndexes.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "428" ": "), "%s", "OTableController::doEditIndexes: no keys got from the indexes supplier!"
); } } while (false)
;
429 }
430 else
431 OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "431" ": "), "%s", "OTableController::doEditIndexes: should never have reached this (no indexes supplier)!"
); } } while (false)
;
432
433 // get the field names
434 Reference< XColumnsSupplier > xColSupp(m_xTable, UNO_QUERY);
435 OSL_ENSURE(xColSupp.is(), "OTableController::doEditIndexes: no columns supplier!")do { if (true && (!(xColSupp.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "435" ": "), "%s", "OTableController::doEditIndexes: no columns supplier!"
); } } while (false)
;
436 if (xColSupp.is())
437 {
438 Reference< XNameAccess > xCols = xColSupp->getColumns();
439 OSL_ENSURE(xCols.is(), "OTableController::doEditIndexes: no columns!")do { if (true && (!(xCols.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "439" ": "), "%s", "OTableController::doEditIndexes: no columns!"
); } } while (false)
;
440 if (xCols.is())
441 aFieldNames = xCols->getElementNames();
442 }
443 }
444 catch( const Exception& )
445 {
446 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "446" ": ", "dbaccess" );
;
447 }
448
449 if (!xIndexes.is())
450 return;
451
452 DbaIndexDialog aDialog(getFrameWeld(), aFieldNames, xIndexes, getConnection(), getORB());
453 if (RET_OK != aDialog.run())
454 return;
455
456}
457
458void OTableController::impl_initialize()
459{
460 try
461 {
462 OTableController_BASE::impl_initialize();
463
464 const NamedValueCollection& rArguments( getInitParams() );
465
466 rArguments.get_ensureType( PROPERTY_CURRENTTABLE"CurrentTable", m_sName );
467
468 // read autoincrement value set in the datasource
469 ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue,m_sAutoIncrementValue);
470
471 assignTable();
472 }
473 catch( const Exception& )
474 {
475 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "475" ": ", "dbaccess" );
;
476 }
477
478 try
479 {
480 ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames,m_aTypeInfo,m_aTypeInfoIndex); // fill the needed type information
481 }
482 catch(const SQLException&)
483 {
484 OSQLWarningBox aWarning(getFrameWeld(), DBA_RES( STR_NO_TYPE_INFO_AVAILABLE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_NO_TYPE_INFO_AVAILABLE" "\004" u8"No type information could be retrieved from the database.\nThe table design mode is not available for this data source."
) )
);
485 aWarning.run();
486 throw;
487 }
488 try
489 {
490 loadData(); // fill the column information from the table
491 getView()->initialize(); // show the windows and fill with our information
492 ClearUndoManager();
493 setModified(false); // and we are not modified yet
494 }
495 catch( const Exception& )
496 {
497 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "497" ": ", "dbaccess" );
;
498 }
499}
500
501bool OTableController::Construct(vcl::Window* pParent)
502{
503 setView( VclPtr<OTableDesignView>::Create( pParent, getORB(), *this ) );
1
Calling 'VclPtr::Create'
3
Returned allocated memory
4
Calling implicit destructor for 'VclPtr<dbaui::ODataView>'
5
Calling '~Reference'
12
Returning from '~Reference'
13
Returning from destructor for 'VclPtr<dbaui::ODataView>'
14
Calling implicit destructor for 'VclPtr<dbaui::OTableDesignView>'
15
Calling '~Reference'
504 OTableController_BASE::Construct(pParent);
505 return true;
506}
507
508sal_Bool SAL_CALL OTableController::suspend(sal_Bool /*_bSuspend*/)
509{
510 if ( getBroadcastHelper().bInDispose || getBroadcastHelper().bDisposed )
511 return true;
512
513 SolarMutexGuard aSolarGuard;
514 ::osl::MutexGuard aGuard( getMutex() );
515 if ( getView() && getView()->IsInModalMode() )
516 return false;
517 if ( getView() )
518 static_cast<OTableDesignView*>(getView())->GrabFocus();
519 bool bCheck = true;
520 if ( isModified() )
521 {
522 if ( std::any_of(m_vRowList.begin(),m_vRowList.end(),
523 std::mem_fn(&OTableRow::isValid)) )
524 {
525 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/tabledesignsavemodifieddialog.ui"));
526 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("TableDesignSaveModifiedDialog"));
527 switch (xQuery->run())
528 {
529 case RET_YES:
530 Execute(ID_BROWSER_SAVEDOC(5000 + 505),Sequence<PropertyValue>());
531 if ( isModified() )
532 bCheck = false; // when we save the table this must be false else some press cancel
533 break;
534 case RET_CANCEL:
535 bCheck = false;
536 break;
537 default:
538 break;
539 }
540 }
541 else if ( !m_bNew )
542 {
543 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(getFrameWeld(), "dbaccess/ui/deleteallrowsdialog.ui"));
544 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("DeleteAllRowsDialog"));
545 switch (xQuery->run())
546 {
547 case RET_YES:
548 {
549 try
550 {
551 Reference<XTablesSupplier> xTablesSup(getConnection(),UNO_QUERY);
552 Reference<XNameAccess> xTables = xTablesSup->getTables();
553 dropTable(xTables,m_sName);
554 }
555 catch(const Exception&)
556 {
557 OSL_FAIL("OTableController::suspend: nothing is expected to happen here!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "557" ": "), "%s", "OTableController::suspend: nothing is expected to happen here!"
); } } while (false)
;
558 }
559
560 }
561 break;
562 case RET_CANCEL:
563 bCheck = false;
564 break;
565 default:
566 break;
567 }
568 }
569 }
570
571 return bCheck;
572}
573
574void OTableController::describeSupportedFeatures()
575{
576 OSingleDocumentController::describeSupportedFeatures();
577
578 implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO(5000 + 700), CommandGroup::EDIT );
579 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC(5000 + 505), CommandGroup::EDIT );
580 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO(5000 + 701), CommandGroup::EDIT );
581 implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC(5000 + 500), CommandGroup::DOCUMENT );
582 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC(5000 + 502), CommandGroup::DOCUMENT );
583 implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 0 )
, CommandGroup::APPLICATION );
584 implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC(5000 + 1312), CommandGroup::EDIT );
585 implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS( 10000 + 923 ) );
586 implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS( 10000 + 924 ) );
587}
588
589void OTableController::impl_onModifyChanged()
590{
591 OSingleDocumentController::impl_onModifyChanged();
592 InvalidateFeature( SID_INDEXDESIGN( ((((((((10000 + 1499) + 1) + 499) + 1) + 100) + 1) + 149) +
1) + 0 )
);
593}
594
595void SAL_CALL OTableController::disposing( const EventObject& _rSource )
596{
597 if ( _rSource.Source == m_xTable )
598 { // some deleted our table so we have a new one
599 stopTableListening();
600 m_xTable = nullptr;
601 m_bNew = true;
602 setModified(true);
603 }
604 else
605 OTableController_BASE::disposing( _rSource );
606}
607
608void OTableController::losingConnection( )
609{
610 // let the base class do its reconnect
611 OTableController_BASE::losingConnection( );
612
613 // remove from the table
614 Reference< XComponent > xComponent(m_xTable, UNO_QUERY);
615 if (xComponent.is())
616 {
617 Reference<XEventListener> xEvtL( static_cast< ::cppu::OWeakObject*>(this), UNO_QUERY);
618 xComponent->removeEventListener(xEvtL);
619 }
620 stopTableListening();
621 m_xTable = nullptr;
622 assignTable();
623 if(!m_xTable.is())
624 {
625 m_bNew = true;
626 setModified(true);
627 }
628 InvalidateAll();
629}
630
631TOTypeInfoSP OTableController::getTypeInfoByType(sal_Int32 _nDataType) const
632{
633 return queryTypeInfoByType(_nDataType,m_aTypeInfo);
634}
635
636void OTableController::appendColumns(Reference<XColumnsSupplier> const & _rxColSup, bool _bNew, bool _bKeyColumns)
637{
638 try
639 {
640 // now append the columns
641 OSL_ENSURE(_rxColSup.is(),"No columns supplier")do { if (true && (!(_rxColSup.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "641" ": "), "%s", "No columns supplier"); } } while (false
)
;
642 if(!_rxColSup.is())
643 return;
644 Reference<XNameAccess> xColumns = _rxColSup->getColumns();
645 OSL_ENSURE(xColumns.is(),"No columns")do { if (true && (!(xColumns.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "645" ": "), "%s", "No columns"); } } while (false)
;
646 Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
647
648 Reference<XAppend> xAppend(xColumns,UNO_QUERY);
649 OSL_ENSURE(xAppend.is(),"No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "649" ": "), "%s", "No XAppend Interface!"); } } while (
false)
;
650
651 for (auto const& row : m_vRowList)
652 {
653 OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "653" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
654 OFieldDescription* pField = row->GetActFieldDescr();
655 if ( !pField || (!_bNew && row->IsReadOnly() && !_bKeyColumns) )
656 continue;
657
658 Reference<XPropertySet> xColumn;
659 if(pField->IsPrimaryKey() || !_bKeyColumns)
660 xColumn = xColumnFactory->createDataDescriptor();
661 if(xColumn.is())
662 {
663 if(!_bKeyColumns)
664 ::dbaui::setColumnProperties(xColumn,pField);
665 else
666 xColumn->setPropertyValue(PROPERTY_NAME"Name",makeAny(pField->GetName()));
667
668 xAppend->appendByDescriptor(xColumn);
669 xColumn = nullptr;
670 // now only the settings are missing
671 if(xColumns->hasByName(pField->GetName()))
672 {
673 xColumns->getByName(pField->GetName()) >>= xColumn;
674 if(xColumn.is())
675 pField->copyColumnSettingsTo(xColumn);
676 }
677 else
678 {
679 OSL_FAIL("OTableController::appendColumns: invalid field name!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "679" ": "), "%s", "OTableController::appendColumns: invalid field name!"
); } } while (false)
;
680 }
681
682 }
683 }
684 }
685 catch(const SQLException& )
686 {
687 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
688 }
689 catch( const Exception& )
690 {
691 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "691" ": ", "dbaccess" );
;
692 }
693}
694
695void OTableController::appendPrimaryKey(Reference<XKeysSupplier> const & _rxSup, bool _bNew)
696{
697 if(!_rxSup.is())
698 return; // the database doesn't support keys
699
700 OSL_ENSURE(_rxSup.is(),"No XKeysSupplier!")do { if (true && (!(_rxSup.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "700" ": "), "%s", "No XKeysSupplier!"); } } while (false
)
;
701 Reference<XIndexAccess> xKeys = _rxSup->getKeys();
702 Reference<XPropertySet> xProp;
703 if (!xKeys.is())
704 return;
705 const sal_Int32 nCount = xKeys->getCount();
706 for(sal_Int32 i=0;i< nCount ;++i)
707 {
708 xKeys->getByIndex(i) >>= xProp;
709 sal_Int32 nKeyType = 0;
710 xProp->getPropertyValue(PROPERTY_TYPE"Type") >>= nKeyType;
711 if(KeyType::PRIMARY == nKeyType)
712 {
713 return; // primary key already exists after appending a column
714 }
715 }
716 Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY);
717 OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!")do { if (true && (!(xKeyFactory.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "717" ": "), "%s", "No XDataDescriptorFactory Interface!"
); } } while (false)
;
718 if ( !xKeyFactory.is() )
719 return;
720 Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
721 OSL_ENSURE(xAppend.is(),"No XAppend Interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "721" ": "), "%s", "No XAppend Interface!"); } } while (
false)
;
722
723 Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
724 OSL_ENSURE(xKey.is(),"Key is null!")do { if (true && (!(xKey.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "724" ": "), "%s", "Key is null!"); } } while (false)
;
725 xKey->setPropertyValue(PROPERTY_TYPE"Type",makeAny(KeyType::PRIMARY));
726
727 Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
728 if(xColSup.is())
729 {
730 appendColumns(xColSup,_bNew,true);
731 Reference<XNameAccess> xColumns = xColSup->getColumns();
732 if(xColumns->hasElements())
733 xAppend->appendByDescriptor(xKey);
734 }
735}
736
737void OTableController::loadData()
738{
739 // if the data structure already exists, empty it
740 m_vRowList.clear();
741
742 std::shared_ptr<OTableRow> pTabEdRow;
743 Reference< XDatabaseMetaData> xMetaData = getMetaData( );
744 // fill data structure with data from DataDefinitionObject
745 if(m_xTable.is() && xMetaData.is())
746 {
747 Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY);
748 OSL_ENSURE(xColSup.is(),"No XColumnsSupplier!")do { if (true && (!(xColSup.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "748" ": "), "%s", "No XColumnsSupplier!"); } } while (false
)
;
749 Reference<XNameAccess> xColumns = xColSup->getColumns();
750 // ReadOnly-Flag
751 // For Drop no row may be editable
752 // For Add only the empty rows may be editable
753 // For Add and Drop all rows can be edited
754 // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
755 bool bIsAlterAllowed = isAlterAllowed();
756
757 const Sequence<OUString> aColNames = xColumns->getElementNames();
758 for(const OUString& rColumn : aColNames)
759 {
760 Reference<XPropertySet> xColumn;
761 xColumns->getByName(rColumn) >>= xColumn;
762 sal_Int32 nType = 0;
763 sal_Int32 nScale = 0;
764 sal_Int32 nPrecision = 0;
765 sal_Int32 nNullable = 0;
766 sal_Int32 nFormatKey = 0;
767 sal_Int32 nAlign = 0;
768
769 bool bIsAutoIncrement = false, bIsCurrency = false;
770 OUString sName,sDescription,sTypeName,sHelpText;
771 Any aControlDefault;
772
773 // get the properties from the column
774 xColumn->getPropertyValue(PROPERTY_NAME"Name") >>= sName;
775 xColumn->getPropertyValue(PROPERTY_TYPENAME"TypeName") >>= sTypeName;
776 xColumn->getPropertyValue(PROPERTY_ISNULLABLE"IsNullable") >>= nNullable;
777 xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT"IsAutoIncrement") >>= bIsAutoIncrement;
778 xColumn->getPropertyValue(PROPERTY_ISCURRENCY"IsCurrency") >>= bIsCurrency;
779 xColumn->getPropertyValue(PROPERTY_TYPE"Type") >>= nType;
780 xColumn->getPropertyValue(PROPERTY_SCALE"Scale") >>= nScale;
781 xColumn->getPropertyValue(PROPERTY_PRECISION"Precision") >>= nPrecision;
782 xColumn->getPropertyValue(PROPERTY_DESCRIPTION"Description") >>= sDescription;
783
784 if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT"HelpText"))
785 xColumn->getPropertyValue(PROPERTY_HELPTEXT"HelpText") >>= sHelpText;
786
787 if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT"ControlDefault"))
788 aControlDefault = xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT"ControlDefault");
789 if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY"FormatKey"))
790 xColumn->getPropertyValue(PROPERTY_FORMATKEY"FormatKey") >>= nFormatKey;
791 if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN"Align"))
792 xColumn->getPropertyValue(PROPERTY_ALIGN"Align") >>= nAlign;
793
794 pTabEdRow = std::make_shared<OTableRow>();
795 pTabEdRow->SetReadOnly(!bIsAlterAllowed);
796 // search for type
797 bool bForce;
798 TOTypeInfoSP pTypeInfo = ::dbaui::getTypeInfoFromType(m_aTypeInfo,nType,sTypeName,"x",nPrecision,nScale,bIsAutoIncrement,bForce);
799 if ( !pTypeInfo )
800 pTypeInfo = m_pTypeInfo;
801 pTabEdRow->SetFieldType( pTypeInfo, bForce );
802
803 OFieldDescription* pActFieldDescr = pTabEdRow->GetActFieldDescr();
804 OSL_ENSURE(pActFieldDescr, "OTableController::loadData: invalid field description generated by the table row!")do { if (true && (!(pActFieldDescr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "804" ": "), "%s", "OTableController::loadData: invalid field description generated by the table row!"
); } } while (false)
;
805 if ( pActFieldDescr )
806 {
807 pActFieldDescr->SetName(sName);
808 pActFieldDescr->SetFormatKey(nFormatKey);
809 pActFieldDescr->SetDescription(sDescription);
810 pActFieldDescr->SetHelpText(sHelpText);
811 pActFieldDescr->SetAutoIncrement(bIsAutoIncrement);
812 pActFieldDescr->SetHorJustify(dbaui::mapTextJustify(nAlign));
813 pActFieldDescr->SetCurrency(bIsCurrency);
814
815 // special data
816 pActFieldDescr->SetIsNullable(nNullable);
817 pActFieldDescr->SetControlDefault(aControlDefault);
818 pActFieldDescr->SetPrecision(nPrecision);
819 pActFieldDescr->SetScale(nScale);
820 }
821 m_vRowList.push_back( pTabEdRow);
822 }
823 // fill the primary key information
824 Reference<XNameAccess> xKeyColumns = getKeyColumns();
825 if(xKeyColumns.is())
826 {
827 const Sequence<OUString> aKeyColumnNames = xKeyColumns->getElementNames();
828 for(const OUString& rKeyColumn : aKeyColumnNames)
829 {
830 for(std::shared_ptr<OTableRow> const& pRow : m_vRowList)
831 {
832 if(pRow->GetActFieldDescr()->GetName() == rKeyColumn)
833 {
834 pRow->SetPrimaryKey(true);
835 break;
836 }
837 }
838 }
839 }
840 }
841
842 // fill empty rows
843
844 OTypeInfoMap::const_iterator aTypeIter = m_aTypeInfo.find(DataType::VARCHAR);
845 if(aTypeIter == m_aTypeInfo.end())
846 aTypeIter = m_aTypeInfo.begin();
847
848 OSL_ENSURE(aTypeIter != m_aTypeInfo.end(),"We have no type information!")do { if (true && (!(aTypeIter != m_aTypeInfo.end())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "848" ": "), "%s", "We have no type information!"); } } while
(false)
;
849
850 bool bReadRow = !isAddAllowed();
851 for(sal_Int32 i=m_vRowList.size(); i < NEWCOLS128; i++ )
852 {
853 pTabEdRow = std::make_shared<OTableRow>();
854 pTabEdRow->SetReadOnly(bReadRow);
855 m_vRowList.push_back( pTabEdRow);
856 }
857}
858
859Reference<XNameAccess> OTableController::getKeyColumns() const
860{
861 return getPrimaryKeyColumns_throw(m_xTable);
862}
863
864bool OTableController::checkColumns(bool _bNew)
865{
866 bool bOk = true;
867 bool bFoundPKey = false;
868 Reference< XDatabaseMetaData > xMetaData = getMetaData( );
869 DatabaseMetaData aMetaData( getConnection() );
870
871 ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
872 std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
873 std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
874 for(;aIter != aEnd;++aIter)
875 {
876 OFieldDescription* pFieldDesc = (*aIter)->GetActFieldDescr();
877 if (pFieldDesc && !pFieldDesc->GetName().isEmpty())
878 {
879 bFoundPKey |= (*aIter)->IsPrimaryKey();
880 // first check for duplicate names
881 bool bDuplicateNameFound = std::any_of(aIter+1, aEnd,
882 [&bCase, &pFieldDesc](const std::shared_ptr<OTableRow>& rxRow) {
883 OFieldDescription* pCompareDesc = rxRow->GetActFieldDescr();
884 return pCompareDesc && bCase(pCompareDesc->GetName(),pFieldDesc->GetName());
885 });
886 if (bDuplicateNameFound)
887 {
888 OUString strMessage = DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_DUPLICATE_NAME" "\004" u8"The table cannot be saved because column name \"$column$\" was assigned twice."
) )
;
889 strMessage = strMessage.replaceFirst("$column$", pFieldDesc->GetName());
890 OSQLWarningBox aWarning(getFrameWeld(), strMessage);
891 aWarning.run();
892 return false;
893 }
894 }
895 }
896 if ( _bNew && !bFoundPKey && aMetaData.supportsPrimaryKeys() )
897 {
898 OUString sTitle(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_NO_PRIM_KEY_HEAD" "\004" u8"No primary key"
) )
);
899 OUString sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_NO_PRIM_KEY" "\004" u8"A unique index or primary key is required for data record identification in this database.\nYou can only enter data into this table when one of these two structural conditions has been met.\n\nShould a primary key be created now?"
) )
);
900 OSQLMessageBox aBox(getFrameWeld(), sTitle,sMsg, MessBoxStyle::YesNoCancel | MessBoxStyle::DefaultYes);
901
902 switch (aBox.run())
903 {
904 case RET_YES:
905 {
906 auto pNewRow = std::make_shared<OTableRow>();
907 TOTypeInfoSP pTypeInfo = ::dbaui::queryPrimaryKeyType(m_aTypeInfo);
908 if ( !pTypeInfo )
909 break;
910
911 pNewRow->SetFieldType( pTypeInfo );
912 OFieldDescription* pActFieldDescr = pNewRow->GetActFieldDescr();
913
914 pActFieldDescr->SetAutoIncrement(false);
915 pActFieldDescr->SetIsNullable(ColumnValue::NO_NULLS);
916
917 pActFieldDescr->SetName( createUniqueName("ID" ));
918 pActFieldDescr->SetPrimaryKey( true );
919 m_vRowList.insert(m_vRowList.begin(),pNewRow);
920
921 static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->Invalidate();
922 static_cast<OTableDesignView*>(getView())->GetEditorCtrl()->RowInserted(0);
923 }
924 break;
925 case RET_CANCEL:
926 bOk = false;
927 break;
928 }
929 }
930 return bOk;
931}
932
933void OTableController::alterColumns()
934{
935 Reference<XColumnsSupplier> xColSup(m_xTable,UNO_QUERY_THROW);
936
937 Reference<XNameAccess> xColumns = xColSup->getColumns();
938 Reference<XIndexAccess> xIdxColumns(xColumns,UNO_QUERY_THROW);
939 OSL_ENSURE(xColumns.is(),"No columns")do { if (true && (!(xColumns.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "939" ": "), "%s", "No columns"); } } while (false)
;
940 if ( !xColumns.is() )
941 return;
942 Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); // can be null
943
944 sal_Int32 nColumnCount = xIdxColumns->getCount();
945 Reference<XDrop> xDrop(xColumns,UNO_QUERY); // can be null
946 Reference<XAppend> xAppend(xColumns,UNO_QUERY); // can be null
947 Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY); // can be null
948
949 bool bReload = false; // refresh the data
950
951 // contains all columns names which are already handled those which are not in the list will be deleted
952 Reference< XDatabaseMetaData> xMetaData = getMetaData( );
953
954 std::set<OUString, comphelper::UStringMixLess> aColumns(
955 comphelper::UStringMixLess(
956 !xMetaData.is()
957 || xMetaData->supportsMixedCaseQuotedIdentifiers()));
958 std::vector< std::shared_ptr<OTableRow> >::const_iterator aIter = m_vRowList.begin();
959 std::vector< std::shared_ptr<OTableRow> >::const_iterator aEnd = m_vRowList.end();
960 // first look for columns where something other than the name changed
961 for(sal_Int32 nPos = 0;aIter != aEnd;++aIter,++nPos)
962 {
963 OSL_ENSURE(*aIter,"OTableRow is null!")do { if (true && (!(*aIter))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "963" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
964 OFieldDescription* pField = (*aIter)->GetActFieldDescr();
965 if ( !pField )
966 continue;
967 if ( (*aIter)->IsReadOnly() )
968 {
969 aColumns.insert(pField->GetName());
970 continue;
971 }
972
973 Reference<XPropertySet> xColumn;
974 if ( xColumns->hasByName(pField->GetName()) )
975 {
976 aColumns.insert(pField->GetName());
977 xColumns->getByName(pField->GetName()) >>= xColumn;
978 OSL_ENSURE(xColumn.is(),"Column is null!")do { if (true && (!(xColumn.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "978" ": "), "%s", "Column is null!"); } } while (false)
;
979
980 sal_Int32 nType=0,nPrecision=0,nScale=0,nNullable=0;
981 bool bAutoIncrement = false;
982 OUString sTypeName,sDescription;
983
984 xColumn->getPropertyValue(PROPERTY_TYPE"Type") >>= nType;
985 xColumn->getPropertyValue(PROPERTY_PRECISION"Precision") >>= nPrecision;
986 xColumn->getPropertyValue(PROPERTY_SCALE"Scale") >>= nScale;
987 xColumn->getPropertyValue(PROPERTY_ISNULLABLE"IsNullable") >>= nNullable;
988 xColumn->getPropertyValue(PROPERTY_ISAUTOINCREMENT"IsAutoIncrement") >>= bAutoIncrement;
989 xColumn->getPropertyValue(PROPERTY_DESCRIPTION"Description") >>= sDescription;
990
991 try { xColumn->getPropertyValue(PROPERTY_TYPENAME"TypeName") >>= sTypeName; }
992 catch( const Exception& )
993 {
994 OSL_FAIL( "no TypeName property?!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "994" ": "), "%s", "no TypeName property?!"); } } while (
false)
;
995 // since this is a last minute fix for #i41785#, I want to be on the safe side,
996 // and catch errors here as early as possible (instead of the whole process of altering
997 // the columns failing)
998 // Normally, sdbcx::Column objects are expected to have a TypeName property
999 }
1000
1001 // check if something changed
1002 if((nType != pField->GetType() ||
1003 sTypeName != pField->GetTypeName() ||
1004 (nPrecision != pField->GetPrecision() && nPrecision ) ||
1005 nScale != pField->GetScale() ||
1006 nNullable != pField->GetIsNullable() ||
1007 sDescription != pField->GetDescription() ||
1008 bAutoIncrement != pField->IsAutoIncrement())&&
1009 xColumnFactory.is())
1010 {
1011 Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor();
1012 ::dbaui::setColumnProperties(xNewColumn,pField);
1013 // first try to alter the column
1014 bool bNotOk = false;
1015 try
1016 {
1017 // first try if we can alter the column
1018 if(xAlter.is())
1019 xAlter->alterColumnByName(pField->GetName(),xNewColumn);
1020 }
1021 catch(const SQLException&)
1022 {
1023 if(xDrop.is() && xAppend.is())
1024 {
1025 OUString aMessage( DBA_RES( STR_TABLEDESIGN_ALTER_ERROR )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_ALTER_ERROR" "\004" u8"The column \"$column$\" could not be changed. Should the column instead be deleted and the new format appended?"
) )
);
1026 aMessage = aMessage.replaceFirst( "$column$", pField->GetName() );
1027
1028 SQLExceptionInfo aError( ::cppu::getCaughtException() );
1029 OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes , &aError);
1030 bNotOk = aMsg.run() == RET_YES;
1031 }
1032 else
1033 throw;
1034 }
1035 // if something went wrong or we can't alter columns
1036 // drop and append a new one
1037 if((!xAlter.is() || bNotOk) && xDrop.is() && xAppend.is())
1038 {
1039 xDrop->dropByName(pField->GetName());
1040 try
1041 {
1042 xAppend->appendByDescriptor(xNewColumn);
1043 }
1044 catch(const SQLException&)
1045 { // an error occurred so we try to reactivate the old one
1046 xAppend->appendByDescriptor(xColumn);
1047 throw;
1048 }
1049 }
1050 // exceptions are caught outside
1051 xNewColumn = nullptr;
1052 if(xColumns->hasByName(pField->GetName()))
1053 xColumns->getByName(pField->GetName()) >>= xColumn;
1054 bReload = true;
1055 }
1056
1057 }
1058 else if(xColumnFactory.is() && xAlter.is() && nPos < nColumnCount)
1059 { // we can't find the column so we could try it with the index before we drop and append a new column
1060 try
1061 {
1062 Reference<XPropertySet> xNewColumn = xColumnFactory->createDataDescriptor();
1063 ::dbaui::setColumnProperties(xNewColumn,pField);
1064 xAlter->alterColumnByIndex(nPos,xNewColumn);
1065 if(xColumns->hasByName(pField->GetName()))
1066 { // ask for the append by name
1067 aColumns.insert(pField->GetName());
1068 xColumns->getByName(pField->GetName()) >>= xColumn;
1069 if(xColumn.is())
1070 pField->copyColumnSettingsTo(xColumn);
1071 }
1072 else
1073 {
1074 OSL_FAIL("OTableController::alterColumns: invalid column (2)!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1074" ": "), "%s", "OTableController::alterColumns: invalid column (2)!"
); } } while (false)
;
1075 }
1076 }
1077 catch(const SQLException&)
1078 { // we couldn't alter the column so we have to add new columns
1079 SQLExceptionInfo aError( ::cppu::getCaughtException() );
1080 bReload = true;
1081 if(xDrop.is() && xAppend.is())
1082 {
1083 OUString aMessage(DBA_RES(STR_TABLEDESIGN_ALTER_ERROR)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_ALTER_ERROR" "\004" u8"The column \"$column$\" could not be changed. Should the column instead be deleted and the new format appended?"
) )
);
1084 aMessage = aMessage.replaceFirst("$column$",pField->GetName());
1085 OSQLWarningBox aMsg(getFrameWeld(), aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, &aError);
1086 if (aMsg.run() != RET_YES)
1087 {
1088 Reference<XPropertySet> xNewColumn(xIdxColumns->getByIndex(nPos),UNO_QUERY_THROW);
1089 OUString sName;
1090 xNewColumn->getPropertyValue(PROPERTY_NAME"Name") >>= sName;
1091 aColumns.insert(sName);
1092 aColumns.insert(pField->GetName());
1093 continue;
1094 }
1095 }
1096 else
1097 throw;
1098 }
1099 }
1100 else
1101 bReload = true;
1102 }
1103 // alter column settings
1104
1105 // first look for columns where something other than the name changed
1106 for (auto const& row : m_vRowList)
1107 {
1108 OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1108" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
1109 OFieldDescription* pField = row->GetActFieldDescr();
1110 if ( !pField )
1111 continue;
1112 if ( row->IsReadOnly() )
1113 {
1114 aColumns.insert(pField->GetName());
1115 continue;
1116 }
1117
1118 Reference<XPropertySet> xColumn;
1119 if ( xColumns->hasByName(pField->GetName()) )
1120 {
1121 xColumns->getByName(pField->GetName()) >>= xColumn;
1122 Reference<XPropertySetInfo> xInfo = xColumn->getPropertySetInfo();
1123 if ( xInfo->hasPropertyByName(PROPERTY_HELPTEXT"HelpText") )
1124 xColumn->setPropertyValue(PROPERTY_HELPTEXT"HelpText",makeAny(pField->GetHelpText()));
1125
1126 if(xInfo->hasPropertyByName(PROPERTY_CONTROLDEFAULT"ControlDefault"))
1127 xColumn->setPropertyValue(PROPERTY_CONTROLDEFAULT"ControlDefault",pField->GetControlDefault());
1128 if(xInfo->hasPropertyByName(PROPERTY_FORMATKEY"FormatKey"))
1129 xColumn->setPropertyValue(PROPERTY_FORMATKEY"FormatKey",makeAny(pField->GetFormatKey()));
1130 if(xInfo->hasPropertyByName(PROPERTY_ALIGN"Align"))
1131 xColumn->setPropertyValue(PROPERTY_ALIGN"Align",makeAny(dbaui::mapTextAllign(pField->GetHorJustify())));
1132 }
1133 }
1134 // second drop all columns which could be found by name
1135 Reference<XNameAccess> xKeyColumns = getKeyColumns();
1136 // now we have to look for the columns who could be deleted
1137 if ( xDrop.is() )
1138 {
1139 const Sequence<OUString> aColNames = xColumns->getElementNames();
1140 for(const OUString& rColumnName : aColNames)
1141 {
1142 if(aColumns.find(rColumnName) == aColumns.end()) // found a column to delete
1143 {
1144 if(xKeyColumns.is() && xKeyColumns->hasByName(rColumnName)) // check if this column is a member of the primary key
1145 {
1146 OUString aMsgT(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TBL_COLUMN_IS_KEYCOLUMN" "\004" u8"The column \"$column$\" belongs to the primary key. If the column is deleted, the primary key will also be deleted. Do you really want to continue?"
) )
);
1147 aMsgT = aMsgT.replaceFirst("$column$",rColumnName);
1148 OUString aTitle(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE" "\004" u8"Primary Key Affected"
) )
);
1149 OSQLMessageBox aMsg(getFrameWeld(), aTitle, aMsgT, MessBoxStyle::YesNo| MessBoxStyle::DefaultYes);
1150 if (aMsg.run() == RET_YES)
1151 {
1152 xKeyColumns = nullptr;
1153 dropPrimaryKey();
1154 }
1155 else
1156 {
1157 bReload = true;
1158 continue;
1159 }
1160 }
1161 try
1162 {
1163 xDrop->dropByName(rColumnName);
1164 }
1165 catch (const SQLException&)
1166 {
1167 OUString sError( DBA_RES( STR_TABLEDESIGN_COULD_NOT_DROP_COL )::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TABLEDESIGN_COULD_NOT_DROP_COL" "\004" u8"The column $column$ could not be deleted."
) )
);
1168 sError = sError.replaceFirst( "$column$", rColumnName );
1169
1170 SQLException aNewException;
1171 aNewException.Message = sError;
1172 aNewException.SQLState = "S1000";
1173 aNewException.NextException = ::cppu::getCaughtException();
1174
1175 throw aNewException;
1176 }
1177 }
1178 }
1179 }
1180
1181 // third append the new columns
1182 for(const auto& rxRow : m_vRowList)
1183 {
1184 OSL_ENSURE(rxRow,"OTableRow is null!")do { if (true && (!(rxRow))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1184" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
1185 OFieldDescription* pField = rxRow->GetActFieldDescr();
1186 if ( !pField || rxRow->IsReadOnly() || aColumns.find(pField->GetName()) != aColumns.end() )
1187 continue;
1188
1189 Reference<XPropertySet> xColumn;
1190 if(!xColumns->hasByName(pField->GetName()))
1191 {
1192 if(xColumnFactory.is() && xAppend.is())
1193 {// column not found by its name so we assume it is new
1194 // Column is new
1195 xColumn = xColumnFactory->createDataDescriptor();
1196 ::dbaui::setColumnProperties(xColumn,pField);
1197 xAppend->appendByDescriptor(xColumn);
1198 if(xColumns->hasByName(pField->GetName()))
1199 { // ask for the append by name
1200 aColumns.insert(pField->GetName());
1201 xColumns->getByName(pField->GetName()) >>= xColumn;
1202 if(xColumn.is())
1203 pField->copyColumnSettingsTo(xColumn);
1204 }
1205 else
1206 {
1207 OSL_FAIL("OTableController::alterColumns: invalid column!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1207" ": "), "%s", "OTableController::alterColumns: invalid column!"
); } } while (false)
;
1208 }
1209 }
1210 }
1211 }
1212
1213 // check if we have to do something with the primary key
1214 bool bNeedDropKey = false;
1215 bool bNeedAppendKey = false;
1216 if ( xKeyColumns.is() )
1217 {
1218 for(const auto& rxRow : m_vRowList)
1219 {
1220 OSL_ENSURE(rxRow,"OTableRow is null!")do { if (true && (!(rxRow))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1220" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
1221 OFieldDescription* pField = rxRow->GetActFieldDescr();
1222 if ( !pField )
1223 continue;
1224
1225 if ( pField->IsPrimaryKey()
1226 && !xKeyColumns->hasByName( pField->GetName() )
1227 )
1228 { // new primary key column inserted which isn't already in the columns selection
1229 bNeedDropKey = bNeedAppendKey = true;
1230 break;
1231 }
1232 else if ( !pField->IsPrimaryKey()
1233 && xKeyColumns->hasByName( pField->GetName() )
1234 )
1235 { // found a column which currently is in the primary key, but is marked not to be anymore
1236 bNeedDropKey = bNeedAppendKey = true;
1237 break;
1238 }
1239 }
1240 }
1241 else
1242 { // no primary key available so we check if we should create one
1243 bNeedAppendKey = true;
1244 }
1245
1246 if ( bNeedDropKey && xKeyColumns.is() && xKeyColumns->getElementNames().hasElements() )
1247 dropPrimaryKey();
1248
1249 if ( bNeedAppendKey )
1250 {
1251 Reference< XKeysSupplier > xKeySup( m_xTable, UNO_QUERY );
1252 appendPrimaryKey( xKeySup ,false);
1253 }
1254
1255 reSyncRows();
1256
1257 if ( bReload )
1258 reload();
1259}
1260
1261void OTableController::dropPrimaryKey()
1262{
1263 SQLExceptionInfo aInfo;
1264 try
1265 {
1266 Reference<XKeysSupplier> xKeySup(m_xTable,UNO_QUERY);
1267 Reference<XIndexAccess> xKeys;
1268 if(xKeySup.is())
1269 xKeys = xKeySup->getKeys();
1270
1271 if(xKeys.is())
1272 {
1273 Reference<XPropertySet> xProp;
1274 for(sal_Int32 i=0;i< xKeys->getCount();++i)
1275 {
1276 xProp.set(xKeys->getByIndex(i),UNO_QUERY);
1277 sal_Int32 nKeyType = 0;
1278 xProp->getPropertyValue(PROPERTY_TYPE"Type") >>= nKeyType;
1279 if(KeyType::PRIMARY == nKeyType)
1280 {
1281 Reference<XDrop> xDrop(xKeys,UNO_QUERY);
1282 xDrop->dropByIndex(i); // delete the key
1283 break;
1284 }
1285 }
1286 }
1287 }
1288 catch(const SQLContext& e)
1289 {
1290 aInfo = SQLExceptionInfo(e);
1291 }
1292 catch(const SQLWarning& e)
1293 {
1294 aInfo = SQLExceptionInfo(e);
1295 }
1296 catch(const SQLException& e)
1297 {
1298 aInfo = SQLExceptionInfo(e);
1299 }
1300 catch( const Exception& )
1301 {
1302 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1302" ": ", "dbaccess" );
;
1303 }
1304
1305 showError(aInfo);
1306}
1307
1308void OTableController::assignTable()
1309{
1310 // get the table
1311 if(m_sName.isEmpty())
1312 return;
1313
1314 Reference<XNameAccess> xNameAccess;
1315 Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY);
1316 if(!xSup.is())
1317 return;
1318
1319 xNameAccess = xSup->getTables();
1320 OSL_ENSURE(xNameAccess.is(),"no nameaccess for the queries!")do { if (true && (!(xNameAccess.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1320" ": "), "%s", "no nameaccess for the queries!"); }
} while (false)
;
1321
1322 if(!xNameAccess->hasByName(m_sName))
1323 return;
1324
1325 Reference<XPropertySet> xProp(xNameAccess->getByName(m_sName), css::uno::UNO_QUERY);
1326 if (!xProp.is())
1327 return;
1328
1329 m_xTable = xProp;
1330 startTableListening();
1331
1332 // check if we set the table editable
1333 Reference<XDatabaseMetaData> xMeta = getConnection()->getMetaData();
1334 setEditable( xMeta.is() && !xMeta->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1335 if(!isEditable())
1336 {
1337 for( const auto& rTableRow : m_vRowList )
1338 {
1339 rTableRow->SetReadOnly();
1340 }
1341 }
1342 m_bNew = false;
1343 // be notified when the table is in disposing
1344 InvalidateAll();
1345}
1346
1347bool OTableController::isAddAllowed() const
1348{
1349 Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
1350 bool bAddAllowed = !m_xTable.is();
1351 if(xColsSup.is())
1352 bAddAllowed = Reference<XAppend>(xColsSup->getColumns(),UNO_QUERY).is();
1353
1354 try
1355 {
1356 Reference< XDatabaseMetaData > xMetaData = getMetaData( );
1357 bAddAllowed = bAddAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithAddColumn());
1358 }
1359 catch(Exception&)
1360 {
1361 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1361" ": ", "dbaccess" );
;
1362 bAddAllowed = false;
1363 }
1364
1365 return bAddAllowed;
1366}
1367
1368bool OTableController::isDropAllowed() const
1369{
1370 Reference<XColumnsSupplier> xColsSup(m_xTable,UNO_QUERY);
1371 bool bDropAllowed = !m_xTable.is();
1372 if(xColsSup.is())
1373 {
1374 Reference<XNameAccess> xNameAccess = xColsSup->getColumns();
1375 bDropAllowed = Reference<XDrop>(xNameAccess,UNO_QUERY).is() && xNameAccess->hasElements();
1376 }
1377
1378 Reference< XDatabaseMetaData> xMetaData = getMetaData( );
1379 bDropAllowed = bDropAllowed || ( xMetaData.is() && xMetaData->supportsAlterTableWithDropColumn());
1380
1381 return bDropAllowed;
1382}
1383
1384bool OTableController::isAlterAllowed() const
1385{
1386 bool bAllowed(!m_xTable.is() || Reference<XAlterTable>(m_xTable,UNO_QUERY).is());
1387 return bAllowed;
1388}
1389
1390void OTableController::reSyncRows()
1391{
1392 bool bAlterAllowed = isAlterAllowed();
1393 bool bAddAllowed = isAddAllowed();
1394 for (auto const& row : m_vRowList)
1395 {
1396 OSL_ENSURE(row,"OTableRow is null!")do { if (true && (!(row))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1396" ": "), "%s", "OTableRow is null!"); } } while (false
)
;
1397 OFieldDescription* pField = row->GetActFieldDescr();
1398 if ( pField )
1399 row->SetReadOnly(!bAlterAllowed);
1400 else
1401 row->SetReadOnly(!bAddAllowed);
1402
1403 }
1404 static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information
1405
1406 ClearUndoManager();
1407 setModified(false); // and we are not modified yet
1408}
1409
1410OUString OTableController::createUniqueName(const OUString& _rName)
1411{
1412 OUString sName = _rName;
1413 Reference< XDatabaseMetaData> xMetaData = getMetaData( );
1414
1415 ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
1416
1417 auto lHasName = [&bCase, &sName](const std::shared_ptr<OTableRow>& rxRow) {
1418 OFieldDescription* pFieldDesc = rxRow->GetActFieldDescr();
1419 return pFieldDesc && !pFieldDesc->GetName().isEmpty() && bCase(sName, pFieldDesc->GetName());
1420 };
1421
1422 sal_Int32 i = 0;
1423 while(std::any_of(m_vRowList.begin(), m_vRowList.end(), lHasName))
1424 {
1425 // found a second name of _rName so we need another
1426 sName = _rName + OUString::number(++i);
1427 }
1428 return sName;
1429}
1430
1431OUString OTableController::getPrivateTitle() const
1432{
1433 OUString sTitle;
1434 try
1435 {
1436 // get the table
1437 if ( !m_sName.isEmpty() && getConnection().is() )
1438 {
1439 if ( m_xTable.is() )
1440 sTitle = ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable, ::dbtools::EComposeRule::InDataManipulation, false );
1441 else
1442 sTitle = m_sName;
1443 }
1444 if ( sTitle.isEmpty() )
1445 {
1446 OUString aName = DBA_RES(STR_TBL_TITLE)::dbaccess::ResourceManager::loadString( reinterpret_cast<
char const *>("STR_TBL_TITLE" "\004" u8"Table #") )
;
1447 sTitle = aName.getToken(0,' ') + OUString::number(getCurrentStartNumber());
1448 }
1449 }
1450 catch( const Exception& )
1451 {
1452 DBG_UNHANDLED_EXCEPTION("dbaccess")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/dbaccess/source/ui/tabledesign/TableController.cxx"
":" "1452" ": ", "dbaccess" );
;
1453 }
1454 return sTitle;
1455}
1456
1457void OTableController::reload()
1458{
1459 loadData(); // fill the column information from the table
1460 static_cast<OTableDesignView*>(getView())->reSync(); // show the windows and fill with our information
1461 ClearUndoManager();
1462 setModified(false); // and we are not modified yet
1463 static_cast<OTableDesignView*>(getView())->Invalidate();
1464}
1465
1466sal_Int32 OTableController::getFirstEmptyRowPosition()
1467{
1468 sal_Int32 nRet = 0;
1469 bool bFoundElem = false;
1470 for (auto const& row : m_vRowList)
1471 {
1472 if ( !row || !row->GetActFieldDescr() || row->GetActFieldDescr()->GetName().isEmpty() )
1473 {
1474 bFoundElem = true;
1475 break;
1476 }
1477 ++nRet;
1478 }
1479 if (!bFoundElem)
1480 {
1481 bool bReadRow = !isAddAllowed();
1482 auto pTabEdRow = std::make_shared<OTableRow>();
1483 pTabEdRow->SetReadOnly(bReadRow);
1484 nRet = m_vRowList.size();
1485 m_vRowList.push_back( pTabEdRow);
1486 }
1487 return nRet;
1488}
1489
1490bool OTableController::isAutoIncrementPrimaryKey() const
1491{
1492 return getSdbMetaData().isAutoIncrementPrimaryKey();
1493}
1494
1495/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
2
Memory is allocated
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
5.1
Field 'm_pBody' is non-null
15.1
Field 'm_pBody' is non-null
)
6
Taking true branch
16
Taking true branch
113 m_pBody->release();
7
Calling 'VclReferenceBase::release'
11
Returning; memory was released
17
Use of memory after it is freed
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
8
Assuming the condition is true
9
Taking true branch
40 delete this;
10
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif