1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
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>
49 #include <connectivity/dbexception.hxx>
50 #include <connectivity/dbtools.hxx>
51 #include <connectivity/dbmetadata.hxx>
52 #include <cppuhelper/exc_hlp.hxx>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <vcl/svapp.hxx>
55 #include <vcl/weld.hxx>
56 #include <o3tl/string_view.hxx>
62 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
63 org_openoffice_comp_dbu_OTableDesign_get_implementation(
64 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
66 return cppu::acquire(new ::dbaui::OTableController(context
));
69 using namespace ::com::sun::star
;
70 using namespace ::com::sun::star::uno
;
71 using namespace ::com::sun::star::io
;
72 using namespace ::com::sun::star::beans
;
73 using namespace ::com::sun::star::frame
;
74 using namespace ::com::sun::star::lang
;
75 using namespace ::com::sun::star::container
;
76 using namespace ::com::sun::star::sdbcx
;
77 using namespace ::com::sun::star::sdbc
;
78 using namespace ::com::sun::star::sdb
;
79 using namespace ::com::sun::star::ui
;
80 using namespace ::com::sun::star::util
;
81 using namespace ::dbtools
;
82 using namespace ::dbaui
;
83 using namespace ::comphelper
;
85 // number of columns when creating it from scratch
90 void dropTable(const Reference
<XNameAccess
>& _rxTable
,const OUString
& _sTableName
)
92 if ( _rxTable
->hasByName(_sTableName
) )
94 Reference
<XDrop
> xNameCont(_rxTable
,UNO_QUERY
);
95 OSL_ENSURE(xNameCont
.is(),"No drop interface for tables!");
97 xNameCont
->dropByName(_sTableName
);
102 OUString SAL_CALL
OTableController::getImplementationName()
104 return "org.openoffice.comp.dbu.OTableDesign";
107 Sequence
< OUString
> OTableController::getSupportedServiceNames()
109 return { "com.sun.star.sdb.TableDesign" };
112 OTableController::OTableController(const Reference
< XComponentContext
>& _rM
) : OTableController_BASE(_rM
)
113 ,m_sTypeNames(DBA_RES(STR_TABLEDESIGN_DBFIELDTYPES
))
114 ,m_bAllowAutoIncrementValue(false)
119 m_pTypeInfo
= std::make_shared
<OTypeInfo
>();
120 m_pTypeInfo
->aUIName
= m_sTypeNames
.getToken(TYPE_OTHER
, ';');
123 OTableController::~OTableController()
125 m_aTypeInfoIndex
.clear();
130 void OTableController::startTableListening()
132 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
134 xComponent
->addEventListener(static_cast<XModifyListener
*>(this));
137 void OTableController::stopTableListening()
139 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
141 xComponent
->removeEventListener(static_cast<XModifyListener
*>(this));
144 void OTableController::disposing()
146 OTableController_BASE::disposing();
152 FeatureState
OTableController::GetState(sal_uInt16 _nId
) const
154 FeatureState aReturn
;
155 // disabled automatically
159 case ID_BROWSER_CLOSE
:
160 aReturn
.bEnabled
= true;
162 case ID_BROWSER_EDITDOC
:
163 aReturn
.bChecked
= isEditable();
164 aReturn
.bEnabled
= true;
166 case ID_BROWSER_SAVEDOC
:
167 aReturn
.bEnabled
= isEditable() && std::any_of(m_vRowList
.begin(),m_vRowList
.end(),std::mem_fn(&OTableRow::isValid
));
169 case ID_BROWSER_SAVEASDOC
:
170 aReturn
.bEnabled
= isConnected() && isEditable();
171 if ( aReturn
.bEnabled
)
173 aReturn
.bEnabled
= std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
174 std::mem_fn(&OTableRow::isValid
));
179 aReturn
.bEnabled
= isEditable() && getView() && static_cast<OTableDesignView
*>(getView())->isCutAllowed();
181 case ID_BROWSER_COPY
:
182 aReturn
.bEnabled
= getView() && static_cast<OTableDesignView
*>(getView())->isCopyAllowed();
184 case ID_BROWSER_PASTE
:
185 aReturn
.bEnabled
= isEditable() && getView() && static_cast<OTableDesignView
*>(getView())->isPasteAllowed();
187 case SID_INDEXDESIGN
:
189 ( ( ((!m_bNew
&& impl_isModified()) || impl_isModified())
190 || Reference
< XIndexesSupplier
>(m_xTable
, UNO_QUERY
).is()
194 if ( aReturn
.bEnabled
)
196 aReturn
.bEnabled
= std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
197 std::mem_fn(&OTableRow::isValid
));
201 aReturn
= OTableController_BASE::GetState(_nId
);
206 void OTableController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
210 case ID_BROWSER_EDITDOC
:
211 setEditable(!isEditable());
212 static_cast<OTableDesignView
*>(getView())->setReadOnly(!isEditable());
213 InvalidateFeature(ID_BROWSER_SAVEDOC
);
214 InvalidateFeature(ID_BROWSER_PASTE
);
215 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
217 case ID_BROWSER_SAVEASDOC
:
220 case ID_BROWSER_SAVEDOC
:
221 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->SaveCurRow();
225 static_cast<OTableDesignView
*>(getView())->cut();
227 case ID_BROWSER_COPY
:
228 static_cast<OTableDesignView
*>(getView())->copy();
230 case ID_BROWSER_PASTE
:
231 static_cast<OTableDesignView
*>(getView())->paste();
233 case SID_INDEXDESIGN
:
237 OTableController_BASE::Execute(_nId
,aArgs
);
239 InvalidateFeature(_nId
);
242 bool OTableController::doSaveDoc(bool _bSaveAs
)
245 reconnect(true); // ask the user for a new connection
246 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
248 if (!xTablesSup
.is())
250 OUString
aMessage(DBA_RES(STR_TABLEDESIGN_CONNECTION_MISSING
));
251 OSQLWarningBox
aWarning(getFrameWeld(), aMessage
);
256 // check if a column exists
259 Reference
<XNameAccess
> xTables
;
260 OUString sCatalog
, sSchema
;
262 bool bNew
= m_sName
.isEmpty();
263 bNew
= bNew
|| m_bNew
|| _bSaveAs
;
267 xTables
= xTablesSup
->getTables();
268 OSL_ENSURE(xTables
.is(),"The tables can't be null!");
269 bNew
= bNew
|| (xTables
.is() && !xTables
->hasByName(m_sName
));
271 // first we need a name for our query so ask the user
274 OUString aName
= DBA_RES(STR_TBL_TITLE
);
275 OUString aDefaultName
= aName
.getToken(0,' ');
276 aDefaultName
= ::dbtools::createUniqueName(xTables
,aDefaultName
);
278 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::TABLE
);
279 OSaveAsDlg
aDlg(getFrameWeld(), CommandType::TABLE
, getORB(), getConnection(), aDefaultName
, aNameChecker
, SADFlags::NONE
);
280 if (aDlg
.run() != RET_OK
)
283 m_sName
= aDlg
.getName();
284 sCatalog
= aDlg
.getCatalog();
285 sSchema
= aDlg
.getSchema();
289 if(m_sName
.isEmpty())
294 OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!");
299 SQLExceptionInfo aInfo
;
302 // check the columns for double names
303 if(!checkColumns(bNew
|| !xTables
->hasByName(m_sName
)))
308 Reference
<XPropertySet
> xTable
;
309 if(bNew
|| !xTables
->hasByName(m_sName
)) // just to make sure the table already exists
311 dropTable(xTables
,m_sName
);
313 Reference
<XDataDescriptorFactory
> xFact(xTables
,UNO_QUERY
);
314 OSL_ENSURE(xFact
.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
315 xTable
= xFact
->createDataDescriptor();
316 OSL_ENSURE(xTable
.is(),"OTableController::doSaveDoc: Create query failed!");
317 // to set the name is only allowed when the query is new
318 xTable
->setPropertyValue(PROPERTY_CATALOGNAME
,Any(sCatalog
));
319 xTable
->setPropertyValue(PROPERTY_SCHEMANAME
,Any(sSchema
));
320 xTable
->setPropertyValue(PROPERTY_NAME
,Any(m_sName
));
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
);
329 // now set the properties
332 Reference
<XAppend
> xAppend(xTables
,UNO_QUERY
);
333 OSL_ENSURE(xAppend
.is(),"OTableController::doSaveDoc: No XAppend Interface!");
334 xAppend
->appendByDescriptor(xTable
);
337 if(!m_xTable
.is()) // correct name and try again
339 // it can be that someone inserted new data for us
340 m_sName
= ::dbtools::composeTableName( getConnection()->getMetaData(), xTable
, ::dbtools::EComposeRule::InDataManipulation
, false );
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() )
348 frame::TitleChangedEvent aEvent
;
349 xEventListener
->titleChanged(aEvent
);
351 releaseNumberForComponent();
353 else if(m_xTable
.is())
360 catch(const SQLContext
& e
)
362 aInfo
= SQLExceptionInfo(e
);
364 catch(const SQLWarning
& e
)
366 aInfo
= SQLExceptionInfo(e
);
368 catch(const SQLException
& e
)
370 aInfo
= SQLExceptionInfo(e
);
372 catch(const ElementExistException
& )
374 OUString
sText( DBA_RES( STR_NAME_ALREADY_EXISTS
) );
375 sText
= sText
.replaceFirst( "#" , m_sName
);
376 OSQLMessageBox
aDlg(getFrameWeld(), DBA_RES( STR_ERROR_DURING_CREATION
), sText
, MessBoxStyle::Ok
, MessageType::Error
);
380 catch( const Exception
& )
382 DBG_UNHANDLED_EXCEPTION("dbaccess");
386 if ( aInfo
.isValid() )
387 aInfo
.prepend( DBA_RES( STR_TABLEDESIGN_SAVE_ERROR
) );
390 if (aInfo
.isValid() || bError
)
395 stopTableListening();
399 return ! (aInfo
.isValid() || bError
);
402 void OTableController::doEditIndexes()
404 // table needs to be saved before editing indexes
405 if (m_bNew
|| isModified())
407 std::unique_ptr
<weld::MessageDialog
> xAsk(Application::CreateMessageDialog(getFrameWeld(),
408 VclMessageType::Question
, VclButtonsType::YesNo
,
409 DBA_RES(STR_QUERY_SAVE_TABLE_EDIT_INDEXES
)));
410 if (RET_YES
!= xAsk
->run())
413 if (!doSaveDoc(false))
416 OSL_ENSURE(!m_bNew
&& !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
419 Reference
< XNameAccess
> xIndexes
; // will be the keys of the table
420 Sequence
< OUString
> aFieldNames
; // will be the column names of the table
424 Reference
< XIndexesSupplier
> xIndexesSupp(m_xTable
, UNO_QUERY
);
425 if (xIndexesSupp
.is())
427 xIndexes
= xIndexesSupp
->getIndexes();
428 OSL_ENSURE(xIndexes
.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
431 OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
433 // get the field names
434 Reference
< XColumnsSupplier
> xColSupp(m_xTable
, UNO_QUERY
);
435 OSL_ENSURE(xColSupp
.is(), "OTableController::doEditIndexes: no columns supplier!");
438 Reference
< XNameAccess
> xCols
= xColSupp
->getColumns();
439 OSL_ENSURE(xCols
.is(), "OTableController::doEditIndexes: no columns!");
441 aFieldNames
= xCols
->getElementNames();
444 catch( const Exception
& )
446 DBG_UNHANDLED_EXCEPTION("dbaccess");
452 DbaIndexDialog
aDialog(getFrameWeld(), aFieldNames
, xIndexes
, getConnection(), getORB());
453 if (RET_OK
!= aDialog
.run())
458 void OTableController::impl_initialize()
462 OTableController_BASE::impl_initialize();
464 const NamedValueCollection
& rArguments( getInitParams() );
466 rArguments
.get_ensureType( PROPERTY_CURRENTTABLE
, m_sName
);
468 // read autoincrement value set in the datasource
469 ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue
,m_sAutoIncrementValue
);
473 catch( const Exception
& )
475 DBG_UNHANDLED_EXCEPTION("dbaccess");
480 ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames
,m_aTypeInfo
,m_aTypeInfoIndex
); // fill the needed type information
482 catch(const SQLException
&)
484 OSQLWarningBox
aWarning(getFrameWeld(), DBA_RES( STR_NO_TYPE_INFO_AVAILABLE
));
490 loadData(); // fill the column information from the table
491 getView()->initialize(); // show the windows and fill with our information
493 setModified(false); // and we are not modified yet
495 catch( const Exception
& )
497 DBG_UNHANDLED_EXCEPTION("dbaccess");
501 bool OTableController::Construct(vcl::Window
* pParent
)
503 setView( VclPtr
<OTableDesignView
>::Create( pParent
, getORB(), *this ) );
504 OTableController_BASE::Construct(pParent
);
508 sal_Bool SAL_CALL
OTableController::suspend(sal_Bool
/*_bSuspend*/)
510 if ( getBroadcastHelper().bInDispose
|| getBroadcastHelper().bDisposed
)
513 SolarMutexGuard aSolarGuard
;
514 ::osl::MutexGuard
aGuard( getMutex() );
515 if ( getView() && getView()->IsInModalMode() )
518 static_cast<OTableDesignView
*>(getView())->GrabFocus();
522 if ( std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
523 std::mem_fn(&OTableRow::isValid
)) )
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())
530 Execute(ID_BROWSER_SAVEDOC
,Sequence
<PropertyValue
>());
532 bCheck
= false; // when we save the table this must be false else some press cancel
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())
551 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
552 Reference
<XNameAccess
> xTables
= xTablesSup
->getTables();
553 dropTable(xTables
,m_sName
);
555 catch(const Exception
&)
557 OSL_FAIL("OTableController::suspend: nothing is expected to happen here!");
574 void OTableController::describeSupportedFeatures()
576 OSingleDocumentController::describeSupportedFeatures();
578 implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO
, CommandGroup::EDIT
);
579 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC
, CommandGroup::EDIT
);
580 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO
, CommandGroup::EDIT
);
581 implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC
, CommandGroup::DOCUMENT
);
582 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
583 implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN
, CommandGroup::APPLICATION
);
584 implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC
, CommandGroup::EDIT
);
585 implDescribeSupportedFeature( ".uno:GetUndoStrings", SID_GETUNDOSTRINGS
);
586 implDescribeSupportedFeature( ".uno:GetRedoStrings", SID_GETREDOSTRINGS
);
589 void OTableController::impl_onModifyChanged()
591 OSingleDocumentController::impl_onModifyChanged();
592 InvalidateFeature( SID_INDEXDESIGN
);
595 void SAL_CALL
OTableController::disposing( const EventObject
& _rSource
)
597 if ( _rSource
.Source
== m_xTable
)
598 { // some deleted our table so we have a new one
599 stopTableListening();
605 OTableController_BASE::disposing( _rSource
);
608 void OTableController::losingConnection( )
610 // let the base class do its reconnect
611 OTableController_BASE::losingConnection( );
613 // remove from the table
614 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
617 Reference
<XEventListener
> xEvtL( static_cast< ::cppu::OWeakObject
*>(this), UNO_QUERY
);
618 xComponent
->removeEventListener(xEvtL
);
620 stopTableListening();
631 TOTypeInfoSP
OTableController::getTypeInfoByType(sal_Int32 _nDataType
) const
633 return queryTypeInfoByType(_nDataType
,m_aTypeInfo
);
636 void OTableController::appendColumns(Reference
<XColumnsSupplier
> const & _rxColSup
, bool _bNew
, bool _bKeyColumns
)
640 // now append the columns
641 OSL_ENSURE(_rxColSup
.is(),"No columns supplier");
644 Reference
<XNameAccess
> xColumns
= _rxColSup
->getColumns();
645 OSL_ENSURE(xColumns
.is(),"No columns");
646 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
);
648 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
);
649 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
651 for (auto const& row
: m_vRowList
)
653 OSL_ENSURE(row
,"OTableRow is null!");
654 OFieldDescription
* pField
= row
->GetActFieldDescr();
655 if ( !pField
|| (!_bNew
&& row
->IsReadOnly() && !_bKeyColumns
) )
658 Reference
<XPropertySet
> xColumn
;
659 if(pField
->IsPrimaryKey() || !_bKeyColumns
)
660 xColumn
= xColumnFactory
->createDataDescriptor();
664 ::dbaui::setColumnProperties(xColumn
,pField
);
666 xColumn
->setPropertyValue(PROPERTY_NAME
,Any(pField
->GetName()));
668 xAppend
->appendByDescriptor(xColumn
);
670 // now only the settings are missing
671 if(xColumns
->hasByName(pField
->GetName()))
673 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
675 pField
->copyColumnSettingsTo(xColumn
);
679 OSL_FAIL("OTableController::appendColumns: invalid field name!");
685 catch(const SQLException
& )
687 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
689 catch( const Exception
& )
691 DBG_UNHANDLED_EXCEPTION("dbaccess");
695 void OTableController::appendPrimaryKey(Reference
<XKeysSupplier
> const & _rxSup
, bool _bNew
)
698 return; // the database doesn't support keys
700 OSL_ENSURE(_rxSup
.is(),"No XKeysSupplier!");
701 Reference
<XIndexAccess
> xKeys
= _rxSup
->getKeys();
702 Reference
<XPropertySet
> xProp
;
705 const sal_Int32 nCount
= xKeys
->getCount();
706 for(sal_Int32 i
=0;i
< nCount
;++i
)
708 xKeys
->getByIndex(i
) >>= xProp
;
709 sal_Int32 nKeyType
= 0;
710 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
711 if(KeyType::PRIMARY
== nKeyType
)
713 return; // primary key already exists after appending a column
716 Reference
<XDataDescriptorFactory
> xKeyFactory(xKeys
,UNO_QUERY
);
717 OSL_ENSURE(xKeyFactory
.is(),"No XDataDescriptorFactory Interface!");
718 if ( !xKeyFactory
.is() )
720 Reference
<XAppend
> xAppend(xKeyFactory
,UNO_QUERY
);
721 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
723 Reference
<XPropertySet
> xKey
= xKeyFactory
->createDataDescriptor();
724 OSL_ENSURE(xKey
.is(),"Key is null!");
725 xKey
->setPropertyValue(PROPERTY_TYPE
,Any(KeyType::PRIMARY
));
727 Reference
<XColumnsSupplier
> xColSup(xKey
,UNO_QUERY
);
730 appendColumns(xColSup
,_bNew
,true);
731 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
732 if(xColumns
->hasElements())
733 xAppend
->appendByDescriptor(xKey
);
737 void OTableController::loadData()
739 // if the data structure already exists, empty it
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())
747 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY
);
748 OSL_ENSURE(xColSup
.is(),"No XColumnsSupplier!");
749 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
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();
757 const Sequence
<OUString
> aColNames
= xColumns
->getElementNames();
758 for(const OUString
& rColumn
: aColNames
)
760 Reference
<XPropertySet
> xColumn
;
761 xColumns
->getByName(rColumn
) >>= xColumn
;
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;
769 bool bIsAutoIncrement
= false, bIsCurrency
= false;
770 OUString sName
,sDescription
,sTypeName
,sHelpText
;
773 // get the properties from the column
774 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
775 xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
;
776 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
777 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bIsAutoIncrement
;
778 xColumn
->getPropertyValue(PROPERTY_ISCURRENCY
) >>= bIsCurrency
;
779 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
780 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
781 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
782 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
784 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT
))
785 xColumn
->getPropertyValue(PROPERTY_HELPTEXT
) >>= sHelpText
;
787 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
788 aControlDefault
= xColumn
->getPropertyValue(PROPERTY_CONTROLDEFAULT
);
789 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY
))
790 xColumn
->getPropertyValue(PROPERTY_FORMATKEY
) >>= nFormatKey
;
791 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN
))
792 xColumn
->getPropertyValue(PROPERTY_ALIGN
) >>= nAlign
;
794 pTabEdRow
= std::make_shared
<OTableRow
>();
795 pTabEdRow
->SetReadOnly(!bIsAlterAllowed
);
798 TOTypeInfoSP pTypeInfo
= ::dbaui::getTypeInfoFromType(m_aTypeInfo
,nType
,sTypeName
,"x",nPrecision
,nScale
,bIsAutoIncrement
,bForce
);
800 pTypeInfo
= m_pTypeInfo
;
801 pTabEdRow
->SetFieldType( pTypeInfo
, bForce
);
803 OFieldDescription
* pActFieldDescr
= pTabEdRow
->GetActFieldDescr();
804 OSL_ENSURE(pActFieldDescr
, "OTableController::loadData: invalid field description generated by the table row!");
805 if ( pActFieldDescr
)
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
);
816 pActFieldDescr
->SetIsNullable(nNullable
);
817 pActFieldDescr
->SetControlDefault(aControlDefault
);
818 pActFieldDescr
->SetPrecision(nPrecision
);
819 pActFieldDescr
->SetScale(nScale
);
821 m_vRowList
.push_back( pTabEdRow
);
823 // fill the primary key information
824 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
827 const Sequence
<OUString
> aKeyColumnNames
= xKeyColumns
->getElementNames();
828 for(const OUString
& rKeyColumn
: aKeyColumnNames
)
830 for(std::shared_ptr
<OTableRow
> const& pRow
: m_vRowList
)
832 if(pRow
->GetActFieldDescr()->GetName() == rKeyColumn
)
834 pRow
->SetPrimaryKey(true);
844 OTypeInfoMap::const_iterator aTypeIter
= m_aTypeInfo
.find(DataType::VARCHAR
);
845 if(aTypeIter
== m_aTypeInfo
.end())
846 aTypeIter
= m_aTypeInfo
.begin();
848 OSL_ENSURE(aTypeIter
!= m_aTypeInfo
.end(),"We have no type information!");
850 bool bReadRow
= !isAddAllowed();
851 for(sal_Int32 i
=m_vRowList
.size(); i
< NEWCOLS
; i
++ )
853 pTabEdRow
= std::make_shared
<OTableRow
>();
854 pTabEdRow
->SetReadOnly(bReadRow
);
855 m_vRowList
.push_back( pTabEdRow
);
859 Reference
<XNameAccess
> OTableController::getKeyColumns() const
861 return getPrimaryKeyColumns_throw(m_xTable
);
864 bool OTableController::checkColumns(bool _bNew
)
867 bool bFoundPKey
= false;
868 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
869 DatabaseMetaData
aMetaData( getConnection() );
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
)
876 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
877 if (pFieldDesc
&& !pFieldDesc
->GetName().isEmpty())
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());
886 if (bDuplicateNameFound
)
888 OUString strMessage
= DBA_RES(STR_TABLEDESIGN_DUPLICATE_NAME
);
889 strMessage
= strMessage
.replaceFirst("$column$", pFieldDesc
->GetName());
890 OSQLWarningBox
aWarning(getFrameWeld(), strMessage
);
896 if ( _bNew
&& !bFoundPKey
&& aMetaData
.supportsPrimaryKeys() )
898 OUString
sTitle(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD
));
899 OUString
sMsg(DBA_RES(STR_TABLEDESIGN_NO_PRIM_KEY
));
900 OSQLMessageBox
aBox(getFrameWeld(), sTitle
,sMsg
, MessBoxStyle::YesNoCancel
| MessBoxStyle::DefaultYes
);
906 auto pNewRow
= std::make_shared
<OTableRow
>();
907 TOTypeInfoSP pTypeInfo
= ::dbaui::queryPrimaryKeyType(m_aTypeInfo
);
911 pNewRow
->SetFieldType( pTypeInfo
);
912 OFieldDescription
* pActFieldDescr
= pNewRow
->GetActFieldDescr();
914 pActFieldDescr
->SetAutoIncrement(false);
915 pActFieldDescr
->SetIsNullable(ColumnValue::NO_NULLS
);
917 pActFieldDescr
->SetName( createUniqueName("ID" ));
918 pActFieldDescr
->SetPrimaryKey( true );
919 m_vRowList
.insert(m_vRowList
.begin(),pNewRow
);
921 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->Invalidate();
922 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->RowInserted(0);
933 void OTableController::alterColumns()
935 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY_THROW
);
937 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
938 Reference
<XIndexAccess
> xIdxColumns(xColumns
,UNO_QUERY_THROW
);
939 OSL_ENSURE(xColumns
.is(),"No columns");
940 if ( !xColumns
.is() )
942 Reference
<XAlterTable
> xAlter(m_xTable
,UNO_QUERY
); // can be null
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
949 bool bReload
= false; // refresh the data
951 // contains all columns names which are already handled those which are not in the list will be deleted
952 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
954 std::set
<OUString
, comphelper::UStringMixLess
> aColumns(
955 comphelper::UStringMixLess(
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
)
963 OSL_ENSURE(*aIter
,"OTableRow is null!");
964 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
967 if ( (*aIter
)->IsReadOnly() )
969 aColumns
.insert(pField
->GetName());
973 Reference
<XPropertySet
> xColumn
;
974 if ( xColumns
->hasByName(pField
->GetName()) )
976 aColumns
.insert(pField
->GetName());
977 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
978 OSL_ENSURE(xColumn
.is(),"Column is null!");
980 sal_Int32 nType
=0,nPrecision
=0,nScale
=0,nNullable
=0;
981 bool bAutoIncrement
= false;
982 OUString sTypeName
,sDescription
;
984 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
985 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
986 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
987 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
988 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bAutoIncrement
;
989 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
991 try { xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
; }
992 catch( const Exception
& )
994 OSL_FAIL( "no TypeName property?!" );
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
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())
1011 Reference
<XPropertySet
> xNewColumn
= xColumnFactory
->createDataDescriptor();
1012 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1013 // first try to alter the column
1014 bool bNotOk
= false;
1017 // first try if we can alter the column
1019 xAlter
->alterColumnByName(pField
->GetName(),xNewColumn
);
1021 catch(const SQLException
&)
1023 if(xDrop
.is() && xAppend
.is())
1025 OUString
aMessage( DBA_RES( STR_TABLEDESIGN_ALTER_ERROR
) );
1026 aMessage
= aMessage
.replaceFirst( "$column$", pField
->GetName() );
1028 SQLExceptionInfo
aError( ::cppu::getCaughtException() );
1029 OSQLWarningBox
aMsg(getFrameWeld(), aMessage
, MessBoxStyle::YesNo
| MessBoxStyle::DefaultYes
, &aError
);
1030 bNotOk
= aMsg
.run() == RET_YES
;
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())
1039 xDrop
->dropByName(pField
->GetName());
1042 xAppend
->appendByDescriptor(xNewColumn
);
1044 catch(const SQLException
&)
1045 { // an error occurred so we try to reactivate the old one
1046 xAppend
->appendByDescriptor(xColumn
);
1050 // exceptions are caught outside
1051 xNewColumn
= nullptr;
1052 if(xColumns
->hasByName(pField
->GetName()))
1053 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
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
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
;
1070 pField
->copyColumnSettingsTo(xColumn
);
1074 OSL_FAIL("OTableController::alterColumns: invalid column (2)!");
1077 catch(const SQLException
&)
1078 { // we couldn't alter the column so we have to add new columns
1079 SQLExceptionInfo
aError( ::cppu::getCaughtException() );
1081 if(xDrop
.is() && xAppend
.is())
1083 OUString
aMessage(DBA_RES(STR_TABLEDESIGN_ALTER_ERROR
));
1084 aMessage
= aMessage
.replaceFirst("$column$",pField
->GetName());
1085 OSQLWarningBox
aMsg(getFrameWeld(), aMessage
, MessBoxStyle::YesNo
| MessBoxStyle::DefaultYes
, &aError
);
1086 if (aMsg
.run() != RET_YES
)
1088 Reference
<XPropertySet
> xNewColumn(xIdxColumns
->getByIndex(nPos
),UNO_QUERY_THROW
);
1090 xNewColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
1091 aColumns
.insert(sName
);
1092 aColumns
.insert(pField
->GetName());
1103 // alter column settings
1105 // first look for columns where something other than the name changed
1106 for (auto const& row
: m_vRowList
)
1108 OSL_ENSURE(row
,"OTableRow is null!");
1109 OFieldDescription
* pField
= row
->GetActFieldDescr();
1112 if ( row
->IsReadOnly() )
1114 aColumns
.insert(pField
->GetName());
1118 Reference
<XPropertySet
> xColumn
;
1119 if ( xColumns
->hasByName(pField
->GetName()) )
1121 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1122 Reference
<XPropertySetInfo
> xInfo
= xColumn
->getPropertySetInfo();
1123 if ( xInfo
->hasPropertyByName(PROPERTY_HELPTEXT
) )
1124 xColumn
->setPropertyValue(PROPERTY_HELPTEXT
,Any(pField
->GetHelpText()));
1126 if(xInfo
->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
1127 xColumn
->setPropertyValue(PROPERTY_CONTROLDEFAULT
,pField
->GetControlDefault());
1128 if(xInfo
->hasPropertyByName(PROPERTY_FORMATKEY
))
1129 xColumn
->setPropertyValue(PROPERTY_FORMATKEY
,Any(pField
->GetFormatKey()));
1130 if(xInfo
->hasPropertyByName(PROPERTY_ALIGN
))
1131 xColumn
->setPropertyValue(PROPERTY_ALIGN
,Any(dbaui::mapTextAlign(pField
->GetHorJustify())));
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
1139 const Sequence
<OUString
> aColNames
= xColumns
->getElementNames();
1140 for(const OUString
& rColumnName
: aColNames
)
1142 if(aColumns
.find(rColumnName
) == aColumns
.end()) // found a column to delete
1144 if(xKeyColumns
.is() && xKeyColumns
->hasByName(rColumnName
)) // check if this column is a member of the primary key
1146 OUString
aMsgT(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN
));
1147 aMsgT
= aMsgT
.replaceFirst("$column$",rColumnName
);
1148 OUString
aTitle(DBA_RES(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE
));
1149 OSQLMessageBox
aMsg(getFrameWeld(), aTitle
, aMsgT
, MessBoxStyle::YesNo
| MessBoxStyle::DefaultYes
);
1150 if (aMsg
.run() == RET_YES
)
1152 xKeyColumns
= nullptr;
1163 xDrop
->dropByName(rColumnName
);
1165 catch (const SQLException
&)
1167 OUString
sError( DBA_RES( STR_TABLEDESIGN_COULD_NOT_DROP_COL
) );
1168 sError
= sError
.replaceFirst( "$column$", rColumnName
);
1170 SQLException aNewException
;
1171 aNewException
.Message
= sError
;
1172 aNewException
.SQLState
= "S1000";
1173 aNewException
.NextException
= ::cppu::getCaughtException();
1175 throw aNewException
;
1181 // third append the new columns
1182 for(const auto& rxRow
: m_vRowList
)
1184 OSL_ENSURE(rxRow
,"OTableRow is null!");
1185 OFieldDescription
* pField
= rxRow
->GetActFieldDescr();
1186 if ( !pField
|| rxRow
->IsReadOnly() || aColumns
.find(pField
->GetName()) != aColumns
.end() )
1189 Reference
<XPropertySet
> xColumn
;
1190 if(!xColumns
->hasByName(pField
->GetName()))
1192 if(xColumnFactory
.is() && xAppend
.is())
1193 {// column not found by its name so we assume it 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
;
1203 pField
->copyColumnSettingsTo(xColumn
);
1207 OSL_FAIL("OTableController::alterColumns: invalid column!");
1213 // check if we have to do something with the primary key
1214 bool bNeedDropKey
= false;
1215 bool bNeedAppendKey
= false;
1216 if ( xKeyColumns
.is() )
1218 for(const auto& rxRow
: m_vRowList
)
1220 OSL_ENSURE(rxRow
,"OTableRow is null!");
1221 OFieldDescription
* pField
= rxRow
->GetActFieldDescr();
1225 if ( pField
->IsPrimaryKey()
1226 && !xKeyColumns
->hasByName( pField
->GetName() )
1228 { // new primary key column inserted which isn't already in the columns selection
1229 bNeedDropKey
= bNeedAppendKey
= true;
1232 else if ( !pField
->IsPrimaryKey()
1233 && xKeyColumns
->hasByName( pField
->GetName() )
1235 { // found a column which currently is in the primary key, but is marked not to be anymore
1236 bNeedDropKey
= bNeedAppendKey
= true;
1242 { // no primary key available so we check if we should create one
1243 bNeedAppendKey
= true;
1246 if ( bNeedDropKey
&& xKeyColumns
.is() && xKeyColumns
->getElementNames().hasElements() )
1249 if ( bNeedAppendKey
)
1251 Reference
< XKeysSupplier
> xKeySup( m_xTable
, UNO_QUERY
);
1252 appendPrimaryKey( xKeySup
,false);
1261 void OTableController::dropPrimaryKey()
1263 SQLExceptionInfo aInfo
;
1266 Reference
<XKeysSupplier
> xKeySup(m_xTable
,UNO_QUERY
);
1267 Reference
<XIndexAccess
> xKeys
;
1269 xKeys
= xKeySup
->getKeys();
1273 Reference
<XPropertySet
> xProp
;
1274 for(sal_Int32 i
=0;i
< xKeys
->getCount();++i
)
1276 xProp
.set(xKeys
->getByIndex(i
),UNO_QUERY
);
1277 sal_Int32 nKeyType
= 0;
1278 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
1279 if(KeyType::PRIMARY
== nKeyType
)
1281 Reference
<XDrop
> xDrop(xKeys
,UNO_QUERY
);
1282 xDrop
->dropByIndex(i
); // delete the key
1288 catch(const SQLContext
& e
)
1290 aInfo
= SQLExceptionInfo(e
);
1292 catch(const SQLWarning
& e
)
1294 aInfo
= SQLExceptionInfo(e
);
1296 catch(const SQLException
& e
)
1298 aInfo
= SQLExceptionInfo(e
);
1300 catch( const Exception
& )
1302 DBG_UNHANDLED_EXCEPTION("dbaccess");
1308 void OTableController::assignTable()
1311 if(m_sName
.isEmpty())
1314 Reference
<XNameAccess
> xNameAccess
;
1315 Reference
<XTablesSupplier
> xSup(getConnection(),UNO_QUERY
);
1319 xNameAccess
= xSup
->getTables();
1320 OSL_ENSURE(xNameAccess
.is(),"no nameaccess for the queries!");
1322 if(!xNameAccess
->hasByName(m_sName
))
1325 Reference
<XPropertySet
> xProp(xNameAccess
->getByName(m_sName
), css::uno::UNO_QUERY
);
1330 startTableListening();
1332 // check if we set the table editable
1333 Reference
<XDatabaseMetaData
> xMeta
= getConnection()->getMetaData();
1334 setEditable( xMeta
.is() && !xMeta
->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1337 for( const auto& rTableRow
: m_vRowList
)
1339 rTableRow
->SetReadOnly();
1343 // be notified when the table is in disposing
1347 bool OTableController::isAddAllowed() const
1349 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1350 bool bAddAllowed
= !m_xTable
.is();
1352 bAddAllowed
= Reference
<XAppend
>(xColsSup
->getColumns(),UNO_QUERY
).is();
1356 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1357 bAddAllowed
= bAddAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithAddColumn());
1361 DBG_UNHANDLED_EXCEPTION("dbaccess");
1362 bAddAllowed
= false;
1368 bool OTableController::isDropAllowed() const
1370 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1371 bool bDropAllowed
= !m_xTable
.is();
1374 Reference
<XNameAccess
> xNameAccess
= xColsSup
->getColumns();
1375 bDropAllowed
= Reference
<XDrop
>(xNameAccess
,UNO_QUERY
).is() && xNameAccess
->hasElements();
1378 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1379 bDropAllowed
= bDropAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithDropColumn());
1381 return bDropAllowed
;
1384 bool OTableController::isAlterAllowed() const
1386 bool bAllowed(!m_xTable
.is() || Reference
<XAlterTable
>(m_xTable
,UNO_QUERY
).is());
1390 void OTableController::reSyncRows()
1392 bool bAlterAllowed
= isAlterAllowed();
1393 bool bAddAllowed
= isAddAllowed();
1394 for (auto const& row
: m_vRowList
)
1396 OSL_ENSURE(row
,"OTableRow is null!");
1397 OFieldDescription
* pField
= row
->GetActFieldDescr();
1399 row
->SetReadOnly(!bAlterAllowed
);
1401 row
->SetReadOnly(!bAddAllowed
);
1404 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1407 setModified(false); // and we are not modified yet
1410 OUString
OTableController::createUniqueName(const OUString
& _rName
)
1412 OUString sName
= _rName
;
1413 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1415 ::comphelper::UStringMixEqual
bCase(!xMetaData
.is() || xMetaData
->supportsMixedCaseQuotedIdentifiers());
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());
1423 while(std::any_of(m_vRowList
.begin(), m_vRowList
.end(), lHasName
))
1425 // found a second name of _rName so we need another
1426 sName
= _rName
+ OUString::number(++i
);
1431 OUString
OTableController::getPrivateTitle() const
1437 if ( !m_sName
.isEmpty() && getConnection().is() )
1439 if ( m_xTable
.is() )
1440 sTitle
= ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable
, ::dbtools::EComposeRule::InDataManipulation
, false );
1444 if ( sTitle
.isEmpty() )
1446 OUString aName
= DBA_RES(STR_TBL_TITLE
);
1447 sTitle
= o3tl::getToken(aName
,0,' ') + OUString::number(getCurrentStartNumber());
1450 catch( const Exception
& )
1452 DBG_UNHANDLED_EXCEPTION("dbaccess");
1457 void OTableController::reload()
1459 loadData(); // fill the column information from the table
1460 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1462 setModified(false); // and we are not modified yet
1463 static_cast<OTableDesignView
*>(getView())->Invalidate();
1466 sal_Int32
OTableController::getFirstEmptyRowPosition()
1469 bool bFoundElem
= false;
1470 for (auto const& row
: m_vRowList
)
1472 if ( !row
|| !row
->GetActFieldDescr() || row
->GetActFieldDescr()->GetName().isEmpty() )
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
);
1490 bool OTableController::isAutoIncrementPrimaryKey() const
1492 return getSdbMetaData().isAutoIncrementPrimaryKey();
1495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */