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 "dbu_reghelper.hxx"
29 #include "dbu_tbl.hrc"
30 #include "dbustrings.hrc"
31 #include "defaultobjectnamecheck.hxx"
32 #include "dlgsave.hxx"
34 #include "indexdialog.hxx"
35 #include "sqlmessage.hxx"
36 #include "uiservices.hxx"
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/frame/FrameSearchFlag.hpp>
41 #include <com/sun/star/frame/XTitleChangeListener.hpp>
42 #include <com/sun/star/frame/XUntitledNumbers.hpp>
43 #include <com/sun/star/io/XActiveDataSink.hpp>
44 #include <com/sun/star/io/XActiveDataSource.hpp>
45 #include <com/sun/star/sdb/CommandType.hpp>
46 #include <com/sun/star/sdb/SQLContext.hpp>
47 #include <com/sun/star/sdbc/ColumnValue.hpp>
48 #include <com/sun/star/sdbc/SQLWarning.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
50 #include <com/sun/star/sdbcx/KeyType.hpp>
51 #include <com/sun/star/sdbcx/XAlterTable.hpp>
52 #include <com/sun/star/sdbcx/XAppend.hpp>
53 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
54 #include <com/sun/star/sdbcx/XDrop.hpp>
55 #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
56 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
57 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
59 #include <comphelper/processfactory.hxx>
60 #include <comphelper/streamsection.hxx>
61 #include <comphelper/types.hxx>
62 #include <connectivity/dbexception.hxx>
63 #include <connectivity/dbtools.hxx>
64 #include <connectivity/dbmetadata.hxx>
65 #include <cppuhelper/exc_hlp.hxx>
66 #include <sfx2/sfxsids.hrc>
67 #include <tools/diagnose_ex.h>
68 #include <vcl/layout.hxx>
70 #include <boost/mem_fn.hpp>
71 #include <boost/bind.hpp>
76 extern "C" void SAL_CALL
createRegistryInfo_OTableControl()
78 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OTableController
> aAutoRegistration
;
81 using namespace ::com::sun::star
;
82 using namespace ::com::sun::star::uno
;
83 using namespace ::com::sun::star::io
;
84 using namespace ::com::sun::star::beans
;
85 using namespace ::com::sun::star::frame
;
86 using namespace ::com::sun::star::lang
;
87 using namespace ::com::sun::star::container
;
88 using namespace ::com::sun::star::sdbcx
;
89 using namespace ::com::sun::star::sdbc
;
90 using namespace ::com::sun::star::sdb
;
91 using namespace ::com::sun::star::ui
;
92 using namespace ::com::sun::star::util
;
93 using namespace ::dbtools
;
94 using namespace ::dbaui
;
95 using namespace ::comphelper
;
97 // number of columns when creating it from scratch
102 void dropTable(const Reference
<XNameAccess
>& _rxTable
,const OUString
& _sTableName
)
104 if ( _rxTable
->hasByName(_sTableName
) )
106 Reference
<XDrop
> xNameCont(_rxTable
,UNO_QUERY
);
107 OSL_ENSURE(xNameCont
.is(),"No drop interface for tables!");
108 if ( xNameCont
.is() )
109 xNameCont
->dropByName(_sTableName
);
114 OUString SAL_CALL
OTableController::getImplementationName() throw( RuntimeException
, std::exception
)
116 return getImplementationName_Static();
119 OUString
OTableController::getImplementationName_Static() throw( RuntimeException
)
121 return OUString("org.openoffice.comp.dbu.OTableDesign");
124 Sequence
< OUString
> OTableController::getSupportedServiceNames_Static() throw( RuntimeException
)
126 Sequence
< OUString
> aSupported(1);
127 aSupported
[0] = "com.sun.star.sdb.TableDesign";
131 Sequence
< OUString
> SAL_CALL
OTableController::getSupportedServiceNames() throw(RuntimeException
, std::exception
)
133 return getSupportedServiceNames_Static();
136 Reference
< XInterface
> SAL_CALL
OTableController::Create(const Reference
<XMultiServiceFactory
>& _rxFactory
)
138 return *(new OTableController(comphelper::getComponentContext(_rxFactory
)));
141 OTableController::OTableController(const Reference
< XComponentContext
>& _rM
) : OTableController_BASE(_rM
)
142 ,m_sTypeNames(ModuleRes(STR_TABLEDESIGN_DBFIELDTYPES
))
144 ,m_bAllowAutoIncrementValue(false)
149 m_pTypeInfo
= TOTypeInfoSP(new OTypeInfo());
150 m_pTypeInfo
->aUIName
= m_sTypeNames
.getToken(TYPE_OTHER
, ';');
153 OTableController::~OTableController()
155 m_aTypeInfoIndex
.clear();
160 void OTableController::startTableListening()
162 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
164 xComponent
->addEventListener(static_cast<XModifyListener
*>(this));
167 void OTableController::stopTableListening()
169 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
171 xComponent
->removeEventListener(static_cast<XModifyListener
*>(this));
174 void OTableController::disposing()
176 OTableController_BASE::disposing();
182 FeatureState
OTableController::GetState(sal_uInt16 _nId
) const
184 FeatureState aReturn
;
185 // disabled automatically
189 case ID_BROWSER_CLOSE
:
190 aReturn
.bEnabled
= true;
192 case ID_BROWSER_EDITDOC
:
193 aReturn
.bChecked
= isEditable();
194 aReturn
.bEnabled
= m_bNew
|| isEditable();// the editable flag is set through this one -> || isAddAllowed() || isDropAllowed() || isAlterAllowed();
196 case ID_BROWSER_SAVEDOC
:
197 aReturn
.bEnabled
= impl_isModified();
198 if ( aReturn
.bEnabled
)
200 aReturn
.bEnabled
= ::std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
201 ::boost::mem_fn(&OTableRow::isValid
));
204 case ID_BROWSER_SAVEASDOC
:
205 aReturn
.bEnabled
= isConnected() && isEditable();
206 if ( aReturn
.bEnabled
)
208 aReturn
.bEnabled
= ::std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
209 ::boost::mem_fn(&OTableRow::isValid
));
214 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCutAllowed();
216 case ID_BROWSER_COPY
:
217 aReturn
.bEnabled
= m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCopyAllowed();
219 case ID_BROWSER_PASTE
:
220 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isPasteAllowed();
222 case SID_INDEXDESIGN
:
224 ( ( ((!m_bNew
&& impl_isModified()) || impl_isModified())
225 || Reference
< XIndexesSupplier
>(m_xTable
, UNO_QUERY
).is()
229 if ( aReturn
.bEnabled
)
231 aReturn
.bEnabled
= ::std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
232 ::boost::mem_fn(&OTableRow::isValid
));
236 aReturn
= OTableController_BASE::GetState(_nId
);
241 void OTableController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
245 case ID_BROWSER_EDITDOC
:
246 setEditable(!isEditable());
247 static_cast<OTableDesignView
*>(getView())->setReadOnly(!isEditable());
248 InvalidateFeature(ID_BROWSER_PASTE
);
249 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
251 case ID_BROWSER_SAVEASDOC
:
254 case ID_BROWSER_SAVEDOC
:
255 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->SaveCurRow();
259 static_cast<OTableDesignView
*>(getView())->cut();
261 case ID_BROWSER_COPY
:
262 static_cast<OTableDesignView
*>(getView())->copy();
264 case ID_BROWSER_PASTE
:
265 static_cast<OTableDesignView
*>(getView())->paste();
267 case SID_INDEXDESIGN
:
271 OTableController_BASE::Execute(_nId
,aArgs
);
273 InvalidateFeature(_nId
);
276 bool OTableController::doSaveDoc(bool _bSaveAs
)
279 reconnect(true); // ask the user for a new connection
280 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
282 if (!xTablesSup
.is())
284 OUString
aMessage(ModuleRes(STR_TABLEDESIGN_CONNECTION_MISSING
));
285 ScopedVclPtrInstance
<OSQLWarningBox
>(getView(), aMessage
)->Execute();
289 // check if a column exists
292 Reference
<XNameAccess
> xTables
;
293 OUString sCatalog
, sSchema
;
295 bool bNew
= m_sName
.isEmpty();
296 bNew
= bNew
|| m_bNew
|| _bSaveAs
;
300 xTables
= xTablesSup
->getTables();
301 OSL_ENSURE(xTables
.is(),"The tables can't be null!");
302 bNew
= bNew
|| (xTables
.is() && !xTables
->hasByName(m_sName
));
304 // first we need a name for our query so ask the user
307 OUString aDefaultName
;
308 if (_bSaveAs
&& !bNew
)
309 aDefaultName
= m_sName
;
312 OUString aName
= ModuleRes(STR_TBL_TITLE
);
313 aDefaultName
= aName
.getToken(0,' ');
314 aDefaultName
= ::dbtools::createUniqueName(xTables
,aDefaultName
);
317 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::TABLE
);
318 ScopedVclPtrInstance
< OSaveAsDlg
> aDlg( getView(), CommandType::TABLE
, getORB(), getConnection(), aDefaultName
, aNameChecker
);
319 if ( aDlg
->Execute() != RET_OK
)
322 m_sName
= aDlg
->getName();
323 sCatalog
= aDlg
->getCatalog();
324 sSchema
= aDlg
->getSchema();
328 if(m_sName
.isEmpty())
333 OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!");
338 SQLExceptionInfo aInfo
;
341 // check the columns for double names
342 if(!checkColumns(bNew
|| !xTables
->hasByName(m_sName
)))
347 Reference
<XPropertySet
> xTable
;
348 if(bNew
|| !xTables
->hasByName(m_sName
)) // just to make sure the table already exists
350 dropTable(xTables
,m_sName
);
352 Reference
<XDataDescriptorFactory
> xFact(xTables
,UNO_QUERY
);
353 OSL_ENSURE(xFact
.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
354 xTable
= xFact
->createDataDescriptor();
355 OSL_ENSURE(xTable
.is(),"OTableController::doSaveDoc: Create query failed!");
356 // to set the name is only allowed when the query is new
357 xTable
->setPropertyValue(PROPERTY_CATALOGNAME
,makeAny(sCatalog
));
358 xTable
->setPropertyValue(PROPERTY_SCHEMANAME
,makeAny(sSchema
));
359 xTable
->setPropertyValue(PROPERTY_NAME
,makeAny(m_sName
));
361 // now append the columns
362 Reference
<XColumnsSupplier
> xColSup(xTable
,UNO_QUERY
);
363 appendColumns(xColSup
,bNew
);
364 // now append the primary key
365 Reference
<XKeysSupplier
> xKeySup(xTable
,UNO_QUERY
);
366 appendPrimaryKey(xKeySup
,bNew
);
368 // now set the properties
371 Reference
<XAppend
> xAppend(xTables
,UNO_QUERY
);
372 OSL_ENSURE(xAppend
.is(),"OTableController::doSaveDoc: No XAppend Interface!");
373 xAppend
->appendByDescriptor(xTable
);
376 if(!m_xTable
.is()) // correct name and try again
378 // it can be that someone inserted new data for us
379 m_sName
= ::dbtools::composeTableName( getConnection()->getMetaData(), xTable
, ::dbtools::eInDataManipulation
, false, false, false );
382 // now check if our datasource has set a tablefilter and if append the new table name to it
383 ::dbaui::appendToFilter(getConnection(),m_sName
,getORB(),getView()); // we are not interessted in the return value
384 Reference
< frame::XTitleChangeListener
> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY
);
385 if ( xEventListener
.is() )
387 frame::TitleChangedEvent aEvent
;
388 xEventListener
->titleChanged(aEvent
);
390 releaseNumberForComponent();
392 else if(m_xTable
.is())
399 catch(const SQLContext
& e
)
401 aInfo
= SQLExceptionInfo(e
);
403 catch(const SQLWarning
& e
)
405 aInfo
= SQLExceptionInfo(e
);
407 catch(const SQLException
& e
)
409 aInfo
= SQLExceptionInfo(e
);
411 catch(const ElementExistException
& )
413 OUString
sText( ModuleRes( STR_NAME_ALREADY_EXISTS
) );
414 sText
= sText
.replaceFirst( "#" , m_sName
);
415 ScopedVclPtrInstance
< OSQLMessageBox
> aDlg( getView(), OUString( ModuleRes( STR_ERROR_DURING_CREATION
) ), sText
, WB_OK
, OSQLMessageBox::Error
);
420 catch( const Exception
& )
423 DBG_UNHANDLED_EXCEPTION();
426 if ( aInfo
.isValid() )
427 aInfo
.prepend( OUString( ModuleRes( STR_TABLEDESIGN_SAVE_ERROR
) ) );
430 if (aInfo
.isValid() || bError
)
435 stopTableListening();
439 return ! (aInfo
.isValid() || bError
);
442 void OTableController::doEditIndexes()
444 // table needs to be saved before editing indexes
445 if (m_bNew
|| isModified())
447 ScopedVclPtrInstance
< MessageDialog
> aAsk(getView(), ModuleRes(STR_QUERY_SAVE_TABLE_EDIT_INDEXES
), VCL_MESSAGE_QUESTION
, VCL_BUTTONS_YES_NO
);
448 if (RET_YES
!= aAsk
->Execute())
451 if (!doSaveDoc(false))
454 OSL_ENSURE(!m_bNew
&& !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
457 Reference
< XNameAccess
> xIndexes
; // will be the keys of the table
458 Sequence
< OUString
> aFieldNames
; // will be the column names of the table
462 Reference
< XIndexesSupplier
> xIndexesSupp(m_xTable
, UNO_QUERY
);
463 if (xIndexesSupp
.is())
465 xIndexes
= xIndexesSupp
->getIndexes();
466 OSL_ENSURE(xIndexes
.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
469 OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
471 // get the field names
472 Reference
< XColumnsSupplier
> xColSupp(m_xTable
, UNO_QUERY
);
473 OSL_ENSURE(xColSupp
.is(), "OTableController::doEditIndexes: no columns supplier!");
476 Reference
< XNameAccess
> xCols
= xColSupp
->getColumns();
477 OSL_ENSURE(xCols
.is(), "OTableController::doEditIndexes: no columns!");
479 aFieldNames
= xCols
->getElementNames();
482 catch( const Exception
& )
484 DBG_UNHANDLED_EXCEPTION();
490 ScopedVclPtrInstance
< DbaIndexDialog
> aDialog(getView(), aFieldNames
, xIndexes
, getConnection(), getORB(), isConnected() && getConnection()->getMetaData().is() ? getConnection()->getMetaData()->getMaxColumnsInIndex() : 0);
491 if (RET_OK
!= aDialog
->Execute())
496 void OTableController::impl_initialize()
500 OTableController_BASE::impl_initialize();
502 const NamedValueCollection
& rArguments( getInitParams() );
504 rArguments
.get_ensureType( OUString(PROPERTY_CURRENTTABLE
), m_sName
);
506 // read autoincrement value set in the datasource
507 ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue
,m_sAutoIncrementValue
);
511 catch( const Exception
& )
513 DBG_UNHANDLED_EXCEPTION();
518 ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames
,m_aTypeInfo
,m_aTypeInfoIndex
); // fill the needed type information
520 catch(const SQLException
&)
522 ScopedVclPtrInstance
<OSQLWarningBox
>(getView(), ModuleRes( STR_NO_TYPE_INFO_AVAILABLE
))->Execute();
527 loadData(); // fill the column information from the table
528 getView()->initialize(); // show the windows and fill with our information
530 setModified(sal_False
); // and we are not modified yet
532 catch( const Exception
& )
534 DBG_UNHANDLED_EXCEPTION();
538 bool OTableController::Construct(vcl::Window
* pParent
)
540 setView( VclPtr
<OTableDesignView
>::Create( pParent
, getORB(), *this ) );
541 OTableController_BASE::Construct(pParent
);
545 sal_Bool SAL_CALL
OTableController::suspend(sal_Bool
/*_bSuspend*/) throw( RuntimeException
, std::exception
)
547 if ( getBroadcastHelper().bInDispose
|| getBroadcastHelper().bDisposed
)
550 SolarMutexGuard aSolarGuard
;
551 ::osl::MutexGuard
aGuard( getMutex() );
552 if ( getView() && getView()->IsInModalMode() )
555 static_cast<OTableDesignView
*>(getView())->GrabFocus();
559 if ( ::std::any_of(m_vRowList
.begin(),m_vRowList
.end(),
560 ::boost::mem_fn(&OTableRow::isValid
)) )
562 ScopedVclPtrInstance
<MessageDialog
> aQry(getView(), "TableDesignSaveModifiedDialog",
563 "dbaccess/ui/tabledesignsavemodifieddialog.ui");
564 switch (aQry
->Execute())
567 Execute(ID_BROWSER_SAVEDOC
,Sequence
<PropertyValue
>());
569 bCheck
= false; // when we save the table this must be false else some press cancel
579 ScopedVclPtrInstance
<MessageDialog
> aQry(getView(), "DeleteAllRowsDialog",
580 "dbaccess/ui/deleteallrowsdialog.ui");
581 switch (aQry
->Execute())
587 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
588 Reference
<XNameAccess
> xTables
= xTablesSup
->getTables();
589 dropTable(xTables
,m_sName
);
591 catch(const Exception
&)
593 OSL_FAIL("OTableController::suspend: nothing is expected to happen here!");
609 void OTableController::describeSupportedFeatures()
611 OSingleDocumentController::describeSupportedFeatures();
613 implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO
, CommandGroup::EDIT
);
614 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC
, CommandGroup::EDIT
);
615 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO
, CommandGroup::EDIT
);
616 implDescribeSupportedFeature( ".uno:HelpMenu", SID_HELPMENU
, CommandGroup::APPLICATION
);
617 implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC
, CommandGroup::DOCUMENT
);
618 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
619 implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN
, CommandGroup::APPLICATION
);
620 implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC
, CommandGroup::EDIT
);
623 void OTableController::impl_onModifyChanged()
625 OSingleDocumentController::impl_onModifyChanged();
626 InvalidateFeature( SID_INDEXDESIGN
);
629 void SAL_CALL
OTableController::disposing( const EventObject
& _rSource
) throw(RuntimeException
, std::exception
)
631 if ( _rSource
.Source
== m_xTable
)
632 { // some deleted our table so we have a new one
633 stopTableListening();
636 setModified(sal_True
);
639 OTableController_BASE::disposing( _rSource
);
642 void OTableController::losingConnection( )
644 // let the base class do it's reconnect
645 OTableController_BASE::losingConnection( );
647 // remove from the table
648 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
651 Reference
<XEventListener
> xEvtL( static_cast< ::cppu::OWeakObject
*>(this), UNO_QUERY
);
652 xComponent
->removeEventListener(xEvtL
);
654 stopTableListening();
660 setModified(sal_True
);
665 TOTypeInfoSP
OTableController::getTypeInfoByType(sal_Int32 _nDataType
) const
667 return queryTypeInfoByType(_nDataType
,m_aTypeInfo
);
670 void OTableController::appendColumns(Reference
<XColumnsSupplier
>& _rxColSup
, bool _bNew
, bool _bKeyColumns
)
674 // now append the columns
675 OSL_ENSURE(_rxColSup
.is(),"No columns supplier");
678 Reference
<XNameAccess
> xColumns
= _rxColSup
->getColumns();
679 OSL_ENSURE(xColumns
.is(),"No columns");
680 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
);
682 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
);
683 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
685 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
686 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
687 for(;aIter
!= aEnd
;++aIter
)
689 OSL_ENSURE(*aIter
,"OTableRow is null!");
690 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
691 if ( !pField
|| (!_bNew
&& (*aIter
)->IsReadOnly() && !_bKeyColumns
) )
694 Reference
<XPropertySet
> xColumn
;
695 if(pField
->IsPrimaryKey() || !_bKeyColumns
)
696 xColumn
= xColumnFactory
->createDataDescriptor();
700 ::dbaui::setColumnProperties(xColumn
,pField
);
702 xColumn
->setPropertyValue(PROPERTY_NAME
,makeAny(pField
->GetName()));
704 xAppend
->appendByDescriptor(xColumn
);
706 // now only the settings are missing
707 if(xColumns
->hasByName(pField
->GetName()))
709 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
711 pField
->copyColumnSettingsTo(xColumn
);
715 OSL_FAIL("OTableController::appendColumns: invalid field name!");
721 catch(const SQLException
& )
723 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
725 catch( const Exception
& )
727 DBG_UNHANDLED_EXCEPTION();
731 void OTableController::appendPrimaryKey(Reference
<XKeysSupplier
>& _rxSup
, bool _bNew
)
734 return; // the database doesn't support keys
736 OSL_ENSURE(_rxSup
.is(),"No XKeysSupplier!");
737 Reference
<XIndexAccess
> xKeys(_rxSup
->getKeys(),UNO_QUERY
);
738 Reference
<XPropertySet
> xProp
;
741 const sal_Int32 nCount
= xKeys
->getCount();
742 for(sal_Int32 i
=0;i
< nCount
;++i
)
744 xKeys
->getByIndex(i
) >>= xProp
;
745 sal_Int32 nKeyType
= 0;
746 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
747 if(KeyType::PRIMARY
== nKeyType
)
749 return; // primary key already exists after appending a column
752 Reference
<XDataDescriptorFactory
> xKeyFactory(xKeys
,UNO_QUERY
);
753 OSL_ENSURE(xKeyFactory
.is(),"No XDataDescriptorFactory Interface!");
754 if ( !xKeyFactory
.is() )
756 Reference
<XAppend
> xAppend(xKeyFactory
,UNO_QUERY
);
757 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
759 Reference
<XPropertySet
> xKey
= xKeyFactory
->createDataDescriptor();
760 OSL_ENSURE(xKey
.is(),"Key is null!");
761 xKey
->setPropertyValue(PROPERTY_TYPE
,makeAny(KeyType::PRIMARY
));
763 Reference
<XColumnsSupplier
> xColSup(xKey
,UNO_QUERY
);
766 appendColumns(xColSup
,_bNew
,true);
767 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
768 if(xColumns
->hasElements())
769 xAppend
->appendByDescriptor(xKey
);
773 void OTableController::loadData()
775 // if the data structure already exists, empty it
778 ::boost::shared_ptr
<OTableRow
> pTabEdRow
;
779 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
780 // fill data structure with data from DataDefinitionObject
781 if(m_xTable
.is() && xMetaData
.is())
783 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY
);
784 OSL_ENSURE(xColSup
.is(),"No XColumnsSupplier!");
785 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
787 // For Drop no row may be editable
788 // For Add only the empty rows may be editable
789 // For Add and Drop all rows can be edited
790 // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
791 bool bIsAlterAllowed
= isAlterAllowed();
792 Sequence
< OUString
> aColumns
= xColumns
->getElementNames();
793 const OUString
* pIter
= aColumns
.getConstArray();
794 const OUString
* pEnd
= pIter
+ aColumns
.getLength();
796 for(;pIter
!= pEnd
;++pIter
)
798 Reference
<XPropertySet
> xColumn
;
799 xColumns
->getByName(*pIter
) >>= xColumn
;
801 sal_Int32 nScale
= 0;
802 sal_Int32 nPrecision
= 0;
803 sal_Int32 nNullable
= 0;
804 sal_Int32 nFormatKey
= 0;
805 sal_Int32 nAlign
= 0;
807 bool bIsAutoIncrement
= false, bIsCurrency
= false;
808 OUString sName
,sDescription
,sTypeName
,sHelpText
;
811 // get the properties from the column
812 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
813 xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
;
814 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
815 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bIsAutoIncrement
;
816 xColumn
->getPropertyValue(PROPERTY_ISCURRENCY
) >>= bIsCurrency
;
817 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
818 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
819 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
820 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
822 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT
))
823 xColumn
->getPropertyValue(PROPERTY_HELPTEXT
) >>= sHelpText
;
825 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
826 aControlDefault
= xColumn
->getPropertyValue(PROPERTY_CONTROLDEFAULT
);
827 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY
))
828 xColumn
->getPropertyValue(PROPERTY_FORMATKEY
) >>= nFormatKey
;
829 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN
))
830 xColumn
->getPropertyValue(PROPERTY_ALIGN
) >>= nAlign
;
832 pTabEdRow
.reset(new OTableRow());
833 pTabEdRow
->SetReadOnly(!bIsAlterAllowed
);
836 OUString
sCreate("x");
837 TOTypeInfoSP pTypeInfo
= ::dbaui::getTypeInfoFromType(m_aTypeInfo
,nType
,sTypeName
,sCreate
,nPrecision
,nScale
,bIsAutoIncrement
,bForce
);
838 if ( !pTypeInfo
.get() )
839 pTypeInfo
= m_pTypeInfo
;
840 pTabEdRow
->SetFieldType( pTypeInfo
, bForce
);
842 OFieldDescription
* pActFieldDescr
= pTabEdRow
->GetActFieldDescr();
843 OSL_ENSURE(pActFieldDescr
, "OTableController::loadData: invalid field description generated by the table row!");
844 if ( pActFieldDescr
)
846 pActFieldDescr
->SetName(sName
);
847 pActFieldDescr
->SetFormatKey(nFormatKey
);
848 pActFieldDescr
->SetDescription(sDescription
);
849 pActFieldDescr
->SetHelpText(sHelpText
);
850 pActFieldDescr
->SetAutoIncrement(bIsAutoIncrement
);
851 pActFieldDescr
->SetHorJustify(dbaui::mapTextJustify(nAlign
));
852 pActFieldDescr
->SetCurrency(bIsCurrency
);
855 pActFieldDescr
->SetIsNullable(nNullable
);
856 pActFieldDescr
->SetControlDefault(aControlDefault
);
857 pActFieldDescr
->SetPrecision(nPrecision
);
858 pActFieldDescr
->SetScale(nScale
);
860 m_vRowList
.push_back( pTabEdRow
);
862 // fill the primary key information
863 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
866 Sequence
< OUString
> aKeyColumns
= xKeyColumns
->getElementNames();
867 const OUString
* pKeyBegin
= aKeyColumns
.getConstArray();
868 const OUString
* pKeyEnd
= pKeyBegin
+ aKeyColumns
.getLength();
870 for(;pKeyBegin
!= pKeyEnd
;++pKeyBegin
)
872 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowIter
= m_vRowList
.begin();
873 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowEnd
= m_vRowList
.end();
874 for(;rowIter
!= rowEnd
;++rowIter
)
876 if((*rowIter
)->GetActFieldDescr()->GetName() == *pKeyBegin
)
878 (*rowIter
)->SetPrimaryKey(true);
888 OTypeInfoMap::iterator aTypeIter
= m_aTypeInfo
.find(DataType::VARCHAR
);
889 if(aTypeIter
== m_aTypeInfo
.end())
890 aTypeIter
= m_aTypeInfo
.begin();
892 OSL_ENSURE(aTypeIter
!= m_aTypeInfo
.end(),"We have no type information!");
894 bool bReadRow
= !isAddAllowed();
895 for(sal_Int32 i
=m_vRowList
.size(); i
< NEWCOLS
; i
++ )
897 pTabEdRow
.reset(new OTableRow());
898 pTabEdRow
->SetReadOnly(bReadRow
);
899 m_vRowList
.push_back( pTabEdRow
);
903 Reference
<XNameAccess
> OTableController::getKeyColumns() const
905 return getPrimaryKeyColumns_throw(m_xTable
);
908 bool OTableController::checkColumns(bool _bNew
)
909 throw(css::sdbc::SQLException
,
910 css::uno::RuntimeException
, std::exception
)
913 bool bFoundPKey
= false;
914 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
915 DatabaseMetaData
aMetaData( getConnection() );
917 ::comphelper::UStringMixEqual
bCase(!xMetaData
.is() || xMetaData
->supportsMixedCaseQuotedIdentifiers());
918 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
919 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
920 for(;aIter
!= aEnd
;++aIter
)
922 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
923 if (pFieldDesc
&& !pFieldDesc
->GetName().isEmpty())
925 bFoundPKey
|= (*aIter
)->IsPrimaryKey();
926 // first check for duplicate names
927 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter2
= aIter
+1;
928 for(;aIter2
!= aEnd
;++aIter2
)
930 OFieldDescription
* pCompareDesc
= (*aIter2
)->GetActFieldDescr();
931 if (pCompareDesc
&& bCase(pCompareDesc
->GetName(),pFieldDesc
->GetName()))
933 OUString strMessage
= ModuleRes(STR_TABLEDESIGN_DUPLICATE_NAME
);
934 strMessage
= strMessage
.replaceFirst("$column$", pFieldDesc
->GetName());
935 ScopedVclPtrInstance
<OSQLWarningBox
>(getView(), strMessage
)->Execute();
941 if ( _bNew
&& !bFoundPKey
&& aMetaData
.supportsPrimaryKeys() )
943 OUString
sTitle(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD
));
944 OUString
sMsg(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY
));
945 ScopedVclPtrInstance
< OSQLMessageBox
> aBox(getView(), sTitle
,sMsg
, WB_YES_NO_CANCEL
| WB_DEF_YES
);
947 switch ( aBox
->Execute() )
951 ::boost::shared_ptr
<OTableRow
> pNewRow(new OTableRow());
952 TOTypeInfoSP pTypeInfo
= ::dbaui::queryPrimaryKeyType(m_aTypeInfo
);
953 if ( !pTypeInfo
.get() )
956 pNewRow
->SetFieldType( pTypeInfo
);
957 OFieldDescription
* pActFieldDescr
= pNewRow
->GetActFieldDescr();
959 pActFieldDescr
->SetAutoIncrement(false);
960 pActFieldDescr
->SetIsNullable(ColumnValue::NO_NULLS
);
962 pActFieldDescr
->SetName( createUniqueName(OUString("ID") ));
963 pActFieldDescr
->SetPrimaryKey( true );
964 m_vRowList
.insert(m_vRowList
.begin(),pNewRow
);
966 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->Invalidate();
967 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->RowInserted(0);
978 void OTableController::alterColumns()
980 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY_THROW
);
981 OSL_ENSURE(xColSup
.is(),"What happen here?!");
983 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
984 Reference
<XIndexAccess
> xIdxColumns(xColumns
,UNO_QUERY_THROW
);
985 OSL_ENSURE(xColumns
.is(),"No columns");
986 if ( !xColumns
.is() )
988 Reference
<XAlterTable
> xAlter(m_xTable
,UNO_QUERY
); // can be null
990 sal_Int32 nColumnCount
= xIdxColumns
->getCount();
991 Reference
<XDrop
> xDrop(xColumns
,UNO_QUERY
); // can be null
992 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
); // can be null
993 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
); // can be null
995 bool bReload
= false; // refresh the data
997 // contains all columns names which are already handled those which are not in the list will be deleted
998 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1000 ::std::map
< OUString
,sal_Bool
,::comphelper::UStringMixLess
> aColumns(!xMetaData
.is() || xMetaData
->supportsMixedCaseQuotedIdentifiers());
1001 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1002 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1003 // first look for columns where something other than the name changed
1005 for(;aIter
!= aEnd
;++aIter
,++nPos
)
1007 OSL_ENSURE(*aIter
,"OTableRow is null!");
1008 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1011 if ( (*aIter
)->IsReadOnly() )
1013 aColumns
[pField
->GetName()] = sal_True
;
1017 Reference
<XPropertySet
> xColumn
;
1018 if ( xColumns
->hasByName(pField
->GetName()) )
1020 aColumns
[pField
->GetName()] = sal_True
;
1021 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1022 OSL_ENSURE(xColumn
.is(),"Column is null!");
1024 sal_Int32 nType
=0,nPrecision
=0,nScale
=0,nNullable
=0;
1025 bool bAutoIncrement
= false;
1026 OUString sTypeName
,sDescription
;
1028 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1029 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
1030 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
1031 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
1032 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bAutoIncrement
;
1033 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
1035 try { xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
; }
1036 catch( const Exception
& )
1038 OSL_FAIL( "no TypeName property?!" );
1039 // since this is a last minute fix for #i41785#, I want to be on the safe side,
1040 // and catch errors here as early as possible (instead of the whole process of altering
1041 // the columns failing)
1042 // Normally, sdbcx::Column objects are expected to have a TypeName property
1045 // check if something changed
1046 if((nType
!= pField
->GetType() ||
1047 sTypeName
!= pField
->GetTypeName() ||
1048 (nPrecision
!= pField
->GetPrecision() && nPrecision
) ||
1049 nScale
!= pField
->GetScale() ||
1050 nNullable
!= pField
->GetIsNullable() ||
1051 sDescription
!= pField
->GetDescription() ||
1052 bAutoIncrement
!= pField
->IsAutoIncrement())&&
1053 xColumnFactory
.is())
1055 Reference
<XPropertySet
> xNewColumn
;
1056 xNewColumn
= xColumnFactory
->createDataDescriptor();
1057 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1058 // first try to alter the column
1059 bool bNotOk
= false;
1062 // first try if we can alter the column
1064 xAlter
->alterColumnByName(pField
->GetName(),xNewColumn
);
1066 catch(const SQLException
&)
1068 if(xDrop
.is() && xAppend
.is())
1070 OUString
aMessage( ModuleRes( STR_TABLEDESIGN_ALTER_ERROR
) );
1071 aMessage
= aMessage
.replaceFirst( "$column$", pField
->GetName() );
1073 SQLExceptionInfo
aError( ::cppu::getCaughtException() );
1074 ScopedVclPtrInstance
< OSQLWarningBox
> aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
, &aError
);
1075 bNotOk
= aMsg
->Execute() == RET_YES
;
1080 // if something went wrong or we can't alter columns
1081 // drop and append a new one
1082 if((!xAlter
.is() || bNotOk
) && xDrop
.is() && xAppend
.is())
1084 xDrop
->dropByName(pField
->GetName());
1087 xAppend
->appendByDescriptor(xNewColumn
);
1089 catch(const SQLException
&)
1090 { // an error occurred so we try to reactivate the old one
1091 xAppend
->appendByDescriptor(xColumn
);
1095 // exceptions are caught outside
1097 if(xColumns
->hasByName(pField
->GetName()))
1098 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1103 else if(xColumnFactory
.is() && xAlter
.is() && nPos
< nColumnCount
)
1104 { // we can't find the column so we could try it with the index before we drop and append a new column
1107 Reference
<XPropertySet
> xNewColumn
;
1108 xNewColumn
= xColumnFactory
->createDataDescriptor();
1109 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1110 xAlter
->alterColumnByIndex(nPos
,xNewColumn
);
1111 if(xColumns
->hasByName(pField
->GetName()))
1112 { // ask for the append by name
1113 aColumns
[pField
->GetName()] = sal_True
;
1114 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1116 pField
->copyColumnSettingsTo(xColumn
);
1120 OSL_FAIL("OTableController::alterColumns: invalid column (2)!");
1123 catch(const SQLException
&)
1124 { // we couldn't alter the column so we have to add new columns
1126 if(xDrop
.is() && xAppend
.is())
1128 OUString
aMessage(ModuleRes(STR_TABLEDESIGN_ALTER_ERROR
));
1129 aMessage
= aMessage
.replaceFirst("$column$",pField
->GetName());
1130 ScopedVclPtrInstance
< OSQLWarningBox
> aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
);
1131 if ( aMsg
->Execute() != RET_YES
)
1133 Reference
<XPropertySet
> xNewColumn(xIdxColumns
->getByIndex(nPos
),UNO_QUERY_THROW
);
1135 xNewColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
1136 aColumns
[sName
] = sal_True
;
1137 aColumns
[pField
->GetName()] = sal_True
;
1148 // alter column settings
1149 aIter
= m_vRowList
.begin();
1151 // first look for columns where something other than the name changed
1152 for(nPos
= 0;aIter
!= aEnd
;++aIter
,++nPos
)
1154 OSL_ENSURE(*aIter
,"OTableRow is null!");
1155 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1158 if ( (*aIter
)->IsReadOnly() )
1160 aColumns
[pField
->GetName()] = sal_True
;
1164 Reference
<XPropertySet
> xColumn
;
1165 if ( xColumns
->hasByName(pField
->GetName()) )
1167 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1168 Reference
<XPropertySetInfo
> xInfo
= xColumn
->getPropertySetInfo();
1169 if ( xInfo
->hasPropertyByName(PROPERTY_HELPTEXT
) )
1170 xColumn
->setPropertyValue(PROPERTY_HELPTEXT
,makeAny(pField
->GetHelpText()));
1172 if(xInfo
->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
1173 xColumn
->setPropertyValue(PROPERTY_CONTROLDEFAULT
,pField
->GetControlDefault());
1174 if(xInfo
->hasPropertyByName(PROPERTY_FORMATKEY
))
1175 xColumn
->setPropertyValue(PROPERTY_FORMATKEY
,makeAny(pField
->GetFormatKey()));
1176 if(xInfo
->hasPropertyByName(PROPERTY_ALIGN
))
1177 xColumn
->setPropertyValue(PROPERTY_ALIGN
,makeAny(dbaui::mapTextAllign(pField
->GetHorJustify())));
1180 // second drop all columns which could be found by name
1181 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
1182 // now we have to look for the columns who could be deleted
1185 Sequence
< OUString
> aColumnNames
= xColumns
->getElementNames();
1186 const OUString
* pIter
= aColumnNames
.getConstArray();
1187 const OUString
* pEnd
= pIter
+ aColumnNames
.getLength();
1188 for(;pIter
!= pEnd
;++pIter
)
1190 if(aColumns
.find(*pIter
) == aColumns
.end()) // found a column to delete
1192 if(xKeyColumns
.is() && xKeyColumns
->hasByName(*pIter
)) // check if this column is a member of the primary key
1194 OUString
aMsgT(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN
));
1195 aMsgT
= aMsgT
.replaceFirst("$column$",*pIter
);
1196 OUString
aTitle(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE
));
1197 ScopedVclPtrInstance
< OSQLMessageBox
> aMsg(getView(),aTitle
,aMsgT
,WB_YES_NO
| WB_DEF_YES
);
1198 if(aMsg
->Execute() == RET_YES
)
1211 xDrop
->dropByName(*pIter
);
1213 catch (const SQLException
&)
1215 OUString
sError( ModuleRes( STR_TABLEDESIGN_COULD_NOT_DROP_COL
) );
1216 sError
= sError
.replaceFirst( "$column$", *pIter
);
1218 SQLException aNewException
;
1219 aNewException
.Message
= sError
;
1220 aNewException
.SQLState
= "S1000";
1221 aNewException
.NextException
= ::cppu::getCaughtException();
1223 throw aNewException
;
1229 // third append the new columns
1230 aIter
= m_vRowList
.begin();
1231 for(;aIter
!= aEnd
;++aIter
)
1233 OSL_ENSURE(*aIter
,"OTableRow is null!");
1234 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1235 if ( !pField
|| (*aIter
)->IsReadOnly() || aColumns
.find(pField
->GetName()) != aColumns
.end() )
1238 Reference
<XPropertySet
> xColumn
;
1239 if(!xColumns
->hasByName(pField
->GetName()))
1241 if(xColumnFactory
.is() && xAppend
.is())
1242 {// column not found by its name so we assume it is new
1244 xColumn
= xColumnFactory
->createDataDescriptor();
1245 ::dbaui::setColumnProperties(xColumn
,pField
);
1246 xAppend
->appendByDescriptor(xColumn
);
1247 if(xColumns
->hasByName(pField
->GetName()))
1248 { // ask for the append by name
1249 aColumns
[pField
->GetName()] = sal_True
;
1250 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1252 pField
->copyColumnSettingsTo(xColumn
);
1256 OSL_FAIL("OTableController::alterColumns: invalid column!");
1262 // check if we have to do something with the primary key
1263 bool bNeedDropKey
= false;
1264 bool bNeedAppendKey
= false;
1265 if ( xKeyColumns
.is() )
1267 aIter
= m_vRowList
.begin();
1268 for(;aIter
!= aEnd
;++aIter
)
1270 OSL_ENSURE(*aIter
,"OTableRow is null!");
1271 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1275 if ( pField
->IsPrimaryKey()
1276 && !xKeyColumns
->hasByName( pField
->GetName() )
1278 { // new primary key column inserted which isn't already in the columns selection
1279 bNeedDropKey
= bNeedAppendKey
= true;
1282 else if ( !pField
->IsPrimaryKey()
1283 && xKeyColumns
->hasByName( pField
->GetName() )
1285 { // found a column which currently is in the primary key, but is marked not to be anymore
1286 bNeedDropKey
= bNeedAppendKey
= true;
1292 { // no primary key available so we check if we should create one
1293 bNeedAppendKey
= true;
1296 if ( bNeedDropKey
&& xKeyColumns
.is() && xKeyColumns
->getElementNames().getLength() )
1299 if ( bNeedAppendKey
)
1301 Reference
< XKeysSupplier
> xKeySup( m_xTable
, UNO_QUERY
);
1302 appendPrimaryKey( xKeySup
,false);
1311 void OTableController::dropPrimaryKey()
1313 SQLExceptionInfo aInfo
;
1316 Reference
<XKeysSupplier
> xKeySup(m_xTable
,UNO_QUERY
);
1317 Reference
<XIndexAccess
> xKeys
;
1319 xKeys
= xKeySup
->getKeys();
1323 Reference
<XPropertySet
> xProp
;
1324 for(sal_Int32 i
=0;i
< xKeys
->getCount();++i
)
1326 xProp
.set(xKeys
->getByIndex(i
),UNO_QUERY
);
1327 sal_Int32 nKeyType
= 0;
1328 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
1329 if(KeyType::PRIMARY
== nKeyType
)
1331 Reference
<XDrop
> xDrop(xKeys
,UNO_QUERY
);
1332 xDrop
->dropByIndex(i
); // delete the key
1338 catch(const SQLContext
& e
)
1340 aInfo
= SQLExceptionInfo(e
);
1342 catch(const SQLWarning
& e
)
1344 aInfo
= SQLExceptionInfo(e
);
1346 catch(const SQLException
& e
)
1348 aInfo
= SQLExceptionInfo(e
);
1350 catch( const Exception
& )
1352 DBG_UNHANDLED_EXCEPTION();
1358 void OTableController::assignTable()
1361 if(!m_sName
.isEmpty())
1363 Reference
<XNameAccess
> xNameAccess
;
1364 Reference
<XTablesSupplier
> xSup(getConnection(),UNO_QUERY
);
1367 xNameAccess
= xSup
->getTables();
1368 OSL_ENSURE(xNameAccess
.is(),"no nameaccess for the queries!");
1370 if(xNameAccess
->hasByName(m_sName
))
1372 Reference
<XPropertySet
> xProp(xNameAccess
->getByName(m_sName
), css::uno::UNO_QUERY
);
1376 startTableListening();
1378 // check if we set the table editable
1379 Reference
<XDatabaseMetaData
> xMeta
= getConnection()->getMetaData();
1380 setEditable( xMeta
.is() && !xMeta
->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1383 ::std::for_each(m_vRowList
.begin(),m_vRowList
.end(),boost::bind( &OTableRow::SetReadOnly
, _1
, true));
1386 // be notified when the table is in disposing
1394 bool OTableController::isAddAllowed() const
1396 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1397 bool bAddAllowed
= !m_xTable
.is();
1399 bAddAllowed
= Reference
<XAppend
>(xColsSup
->getColumns(),UNO_QUERY
).is();
1403 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1404 bAddAllowed
= bAddAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithAddColumn());
1408 DBG_UNHANDLED_EXCEPTION();
1409 bAddAllowed
= false;
1415 bool OTableController::isDropAllowed() const
1417 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1418 bool bDropAllowed
= !m_xTable
.is();
1421 Reference
<XNameAccess
> xNameAccess
= xColsSup
->getColumns();
1422 bDropAllowed
= Reference
<XDrop
>(xNameAccess
,UNO_QUERY
).is() && xNameAccess
->hasElements();
1425 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1426 bDropAllowed
= bDropAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithDropColumn());
1428 return bDropAllowed
;
1431 bool OTableController::isAlterAllowed() const
1433 bool bAllowed(!m_xTable
.is() || Reference
<XAlterTable
>(m_xTable
,UNO_QUERY
).is());
1437 void OTableController::reSyncRows()
1439 bool bAlterAllowed
= isAlterAllowed();
1440 bool bAddAllowed
= isAddAllowed();
1441 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1442 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1443 for(;aIter
!= aEnd
;++aIter
)
1445 OSL_ENSURE(*aIter
,"OTableRow is null!");
1446 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1448 (*aIter
)->SetReadOnly(!bAlterAllowed
);
1450 (*aIter
)->SetReadOnly(!bAddAllowed
);
1453 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1456 setModified(sal_False
); // and we are not modified yet
1459 OUString
OTableController::createUniqueName(const OUString
& _rName
)
1461 OUString sName
= _rName
;
1462 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1464 ::comphelper::UStringMixEqual
bCase(!xMetaData
.is() || xMetaData
->supportsMixedCaseQuotedIdentifiers());
1466 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1467 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1468 for(sal_Int32 i
=0;aIter
!= aEnd
;++aIter
)
1470 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
1471 if (pFieldDesc
&& !pFieldDesc
->GetName().isEmpty() && bCase(sName
,pFieldDesc
->GetName()))
1472 { // found a second name of _rName so we need another
1473 sName
= _rName
+ OUString::number(++i
);
1474 aIter
= m_vRowList
.begin(); // and retry
1480 OUString
OTableController::getPrivateTitle() const
1486 if ( !m_sName
.isEmpty() && getConnection().is() )
1488 if ( m_xTable
.is() )
1489 sTitle
= ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable
, ::dbtools::eInDataManipulation
, false, false, false );
1493 if ( sTitle
.isEmpty() )
1495 OUString aName
= ModuleRes(STR_TBL_TITLE
);
1496 sTitle
= aName
.getToken(0,' ');
1497 sTitle
+= OUString::number(getCurrentStartNumber());
1500 catch( const Exception
& )
1502 DBG_UNHANDLED_EXCEPTION();
1507 void OTableController::reload()
1509 loadData(); // fill the column information from the table
1510 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1512 setModified(sal_False
); // and we are not modified yet
1513 static_cast<OTableDesignView
*>(getView())->Invalidate();
1516 sal_Int32
OTableController::getFirstEmptyRowPosition()
1518 sal_Int32 nRet
= -1;
1519 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1520 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1521 for(;aIter
!= aEnd
;++aIter
)
1523 if ( !*aIter
|| !(*aIter
)->GetActFieldDescr() || (*aIter
)->GetActFieldDescr()->GetName().isEmpty() )
1525 nRet
= aIter
- m_vRowList
.begin();
1531 bool bReadRow
= !isAddAllowed();
1532 ::boost::shared_ptr
<OTableRow
> pTabEdRow(new OTableRow());
1533 pTabEdRow
->SetReadOnly(bReadRow
);
1534 nRet
= m_vRowList
.size();
1535 m_vRowList
.push_back( pTabEdRow
);
1540 bool OTableController::isAutoIncrementPrimaryKey() const
1542 return getSdbMetaData().isAutoIncrementPrimaryKey();
1545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */