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 .
21 #include "FieldDescriptions.hxx"
22 #include "TEditControl.hxx"
23 #include "TableController.hxx"
24 #include "TableDesignView.hxx"
25 #include "TableRow.hxx"
26 #include "TypeInfo.hxx"
27 #include "UITools.hxx"
28 #include "browserids.hxx"
29 #include "dbu_reghelper.hxx"
30 #include "dbu_tbl.hrc"
31 #include "dbustrings.hrc"
32 #include "defaultobjectnamecheck.hxx"
33 #include "dlgsave.hxx"
35 #include "indexdialog.hxx"
36 #include "sqlmessage.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/extract.hxx>
60 #include <comphelper/processfactory.hxx>
61 #include <comphelper/streamsection.hxx>
62 #include <comphelper/types.hxx>
63 #include <connectivity/dbexception.hxx>
64 #include <connectivity/dbtools.hxx>
65 #include <connectivity/dbmetadata.hxx>
66 #include <cppuhelper/exc_hlp.hxx>
67 #include <sfx2/sfxsids.hrc>
68 #include <tools/diagnose_ex.h>
69 #include <tools/string.hxx>
70 #include <vcl/msgbox.hxx>
72 #include <boost/mem_fn.hpp>
73 #include <boost/bind.hpp>
78 extern "C" void SAL_CALL
createRegistryInfo_OTableControl()
80 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OTableController
> aAutoRegistration
;
83 using namespace ::com::sun::star
;
84 using namespace ::com::sun::star::uno
;
85 using namespace ::com::sun::star::io
;
86 using namespace ::com::sun::star::beans
;
87 using namespace ::com::sun::star::frame
;
88 using namespace ::com::sun::star::lang
;
89 using namespace ::com::sun::star::container
;
90 using namespace ::com::sun::star::sdbcx
;
91 using namespace ::com::sun::star::sdbc
;
92 using namespace ::com::sun::star::sdb
;
93 using namespace ::com::sun::star::ui
;
94 using namespace ::com::sun::star::util
;
95 using namespace ::dbtools
;
96 using namespace ::dbaui
;
97 using namespace ::comphelper
;
99 // Anzahl Spalten beim Neuanlegen
104 void dropTable(const Reference
<XNameAccess
>& _rxTable
,const OUString
& _sTableName
)
106 if ( _rxTable
->hasByName(_sTableName
) )
108 Reference
<XDrop
> xNameCont(_rxTable
,UNO_QUERY
);
109 OSL_ENSURE(xNameCont
.is(),"No drop interface for tables!");
110 if ( xNameCont
.is() )
111 xNameCont
->dropByName(_sTableName
);
114 //------------------------------------------------------------------------------
115 struct OTableRowCompare
: public ::std::binary_function
< ::boost::shared_ptr
<OTableRow
> , OUString
, bool>
117 bool operator() (const ::boost::shared_ptr
<OTableRow
> lhs
, const OUString
& rhs
) const
119 OFieldDescription
* pField
= lhs
->GetActFieldDescr();
120 return pField
&& pField
->GetName() == rhs
;
126 //------------------------------------------------------------------------------
127 OUString SAL_CALL
OTableController::getImplementationName() throw( RuntimeException
)
129 return getImplementationName_Static();
132 //------------------------------------------------------------------------------
133 OUString
OTableController::getImplementationName_Static() throw( RuntimeException
)
135 return OUString("org.openoffice.comp.dbu.OTableDesign");
137 //------------------------------------------------------------------------------
138 Sequence
< OUString
> OTableController::getSupportedServiceNames_Static(void) throw( RuntimeException
)
140 Sequence
< OUString
> aSupported(1);
141 aSupported
.getArray()[0] = OUString("com.sun.star.sdb.TableDesign");
144 //-------------------------------------------------------------------------
145 Sequence
< OUString
> SAL_CALL
OTableController::getSupportedServiceNames() throw(RuntimeException
)
147 return getSupportedServiceNames_Static();
149 // -------------------------------------------------------------------------
150 Reference
< XInterface
> SAL_CALL
OTableController::Create(const Reference
<XMultiServiceFactory
>& _rxFactory
)
152 return *(new OTableController(comphelper::getComponentContext(_rxFactory
)));
155 DBG_NAME(OTableController
)
156 // -----------------------------------------------------------------------------
157 OTableController::OTableController(const Reference
< XComponentContext
>& _rM
) : OTableController_BASE(_rM
)
158 ,m_sTypeNames(ModuleRes(STR_TABLEDESIGN_DBFIELDTYPES
))
160 ,m_bAllowAutoIncrementValue(sal_False
)
163 DBG_CTOR(OTableController
,NULL
);
166 m_pTypeInfo
= TOTypeInfoSP(new OTypeInfo());
167 m_pTypeInfo
->aUIName
= m_sTypeNames
.GetToken(TYPE_OTHER
);
169 // -----------------------------------------------------------------------------
170 OTableController::~OTableController()
172 m_aTypeInfoIndex
.clear();
175 DBG_DTOR(OTableController
,NULL
);
178 // -----------------------------------------------------------------------------
179 void OTableController::startTableListening()
181 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
183 xComponent
->addEventListener(static_cast<XModifyListener
*>(this));
186 // -----------------------------------------------------------------------------
187 void OTableController::stopTableListening()
189 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
191 xComponent
->removeEventListener(static_cast<XModifyListener
*>(this));
194 // -----------------------------------------------------------------------------
195 void OTableController::disposing()
197 OTableController_BASE::disposing();
202 // -----------------------------------------------------------------------------
203 FeatureState
OTableController::GetState(sal_uInt16 _nId
) const
205 FeatureState aReturn
;
206 // (disabled automatically)
210 case ID_BROWSER_CLOSE
:
211 aReturn
.bEnabled
= sal_True
;
213 case ID_BROWSER_EDITDOC
:
214 aReturn
.bChecked
= isEditable();
215 aReturn
.bEnabled
= m_bNew
|| isEditable();// the editable flag is set through this one -> || isAddAllowed() || isDropAllowed() || isAlterAllowed();
217 case ID_BROWSER_SAVEDOC
:
218 aReturn
.bEnabled
= impl_isModified();
219 if ( aReturn
.bEnabled
)
221 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
222 ::boost::mem_fn(&OTableRow::isValid
));
223 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
226 case ID_BROWSER_SAVEASDOC
:
227 aReturn
.bEnabled
= isConnected() && isEditable();
228 if ( aReturn
.bEnabled
)
230 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
231 ::boost::mem_fn(&OTableRow::isValid
));
232 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
237 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCutAllowed();
239 case ID_BROWSER_COPY
:
240 aReturn
.bEnabled
= m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCopyAllowed();
242 case ID_BROWSER_PASTE
:
243 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isPasteAllowed();
245 case SID_INDEXDESIGN
:
247 ( ( ((!m_bNew
&& impl_isModified()) || impl_isModified())
248 || Reference
< XIndexesSupplier
>(m_xTable
, UNO_QUERY
).is()
252 if ( aReturn
.bEnabled
)
254 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
255 ::boost::mem_fn(&OTableRow::isValid
));
256 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
260 aReturn
= OTableController_BASE::GetState(_nId
);
264 // -----------------------------------------------------------------------------
265 void OTableController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
269 case ID_BROWSER_EDITDOC
:
270 setEditable(!isEditable());
271 static_cast<OTableDesignView
*>(getView())->setReadOnly(!isEditable());
272 InvalidateFeature(ID_BROWSER_PASTE
);
273 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
275 case ID_BROWSER_SAVEASDOC
:
278 case ID_BROWSER_SAVEDOC
:
279 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->SaveCurRow();
280 doSaveDoc(sal_False
);
283 static_cast<OTableDesignView
*>(getView())->cut();
285 case ID_BROWSER_COPY
:
286 static_cast<OTableDesignView
*>(getView())->copy();
288 case ID_BROWSER_PASTE
:
289 static_cast<OTableDesignView
*>(getView())->paste();
291 case SID_INDEXDESIGN
:
295 OTableController_BASE::Execute(_nId
,aArgs
);
297 InvalidateFeature(_nId
);
300 // -----------------------------------------------------------------------------
301 sal_Bool
OTableController::doSaveDoc(sal_Bool _bSaveAs
)
304 reconnect(sal_True
); // ask the user for a new connection
305 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
307 if (!xTablesSup
.is())
309 String
aMessage(ModuleRes(STR_TABLEDESIGN_CONNECTION_MISSING
));
310 OSQLWarningBox( getView(), aMessage
).Execute();
314 // check if a column exists
317 Reference
<XNameAccess
> xTables
;
318 OUString sCatalog
, sSchema
;
320 sal_Bool bNew
= m_sName
.isEmpty();
321 bNew
= bNew
|| m_bNew
|| _bSaveAs
;
325 xTables
= xTablesSup
->getTables();
326 OSL_ENSURE(xTables
.is(),"The tables can't be null!");
327 bNew
= bNew
|| (xTables
.is() && !xTables
->hasByName(m_sName
));
329 // first we need a name for our query so ask the user
333 if (_bSaveAs
&& !bNew
)
334 aDefaultName
= String(m_sName
);
337 String aName
= String(ModuleRes(STR_TBL_TITLE
));
338 aDefaultName
= aName
.GetToken(0,' ');
339 aDefaultName
= ::dbtools::createUniqueName(xTables
,aDefaultName
);
342 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::TABLE
);
343 OSaveAsDlg
aDlg( getView(), CommandType::TABLE
, getORB(), getConnection(), aDefaultName
, aNameChecker
);
344 if ( aDlg
.Execute() != RET_OK
)
347 m_sName
= aDlg
.getName();
348 sCatalog
= aDlg
.getCatalog();
349 sSchema
= aDlg
.getSchema();
353 if(m_sName
.isEmpty())
358 OSL_FAIL("OTableController::doSaveDoc: nothing is expected to happen here!");
361 sal_Bool bAlter
= sal_False
;
362 sal_Bool bError
= sal_False
;
363 SQLExceptionInfo aInfo
;
366 // check the columns for double names
367 if(!checkColumns(bNew
|| !xTables
->hasByName(m_sName
)))
372 Reference
<XPropertySet
> xTable
;
373 if(bNew
|| !xTables
->hasByName(m_sName
)) // just to make sure the table already exists
375 dropTable(xTables
,m_sName
);
377 Reference
<XDataDescriptorFactory
> xFact(xTables
,UNO_QUERY
);
378 OSL_ENSURE(xFact
.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
379 xTable
= xFact
->createDataDescriptor();
380 OSL_ENSURE(xTable
.is(),"OTableController::doSaveDoc: Create query failed!");
381 // to set the name is only allowed when the wuery is new
382 xTable
->setPropertyValue(PROPERTY_CATALOGNAME
,makeAny(sCatalog
));
383 xTable
->setPropertyValue(PROPERTY_SCHEMANAME
,makeAny(sSchema
));
384 xTable
->setPropertyValue(PROPERTY_NAME
,makeAny(m_sName
));
386 // now append the columns
387 Reference
<XColumnsSupplier
> xColSup(xTable
,UNO_QUERY
);
388 appendColumns(xColSup
,bNew
);
389 // now append the primary key
390 Reference
<XKeysSupplier
> xKeySup(xTable
,UNO_QUERY
);
391 appendPrimaryKey(xKeySup
,bNew
);
393 // now set the properties
396 Reference
<XAppend
> xAppend(xTables
,UNO_QUERY
);
397 OSL_ENSURE(xAppend
.is(),"OTableController::doSaveDoc: No XAppend Interface!");
398 xAppend
->appendByDescriptor(xTable
);
401 if(!m_xTable
.is()) // correct name and try again
403 // it can be that someone inserted new data for us
404 m_sName
= ::dbtools::composeTableName( getConnection()->getMetaData(), xTable
, ::dbtools::eInDataManipulation
, false, false, false );
407 // now check if our datasource has set a tablefilter and if append the new table name to it
408 ::dbaui::appendToFilter(getConnection(),m_sName
,getORB(),getView()); // we are not interessted in the return value
409 Reference
< frame::XTitleChangeListener
> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY
);
410 if ( xEventListener
.is() )
412 frame::TitleChangedEvent aEvent
;
413 xEventListener
->titleChanged(aEvent
);
415 releaseNumberForComponent();
417 else if(m_xTable
.is())
424 catch(const SQLContext
& e
)
426 aInfo
= SQLExceptionInfo(e
);
428 catch(const SQLWarning
& e
)
430 aInfo
= SQLExceptionInfo(e
);
432 catch(const SQLException
& e
)
434 aInfo
= SQLExceptionInfo(e
);
436 catch(const ElementExistException
& )
438 String
sText( ModuleRes( STR_NAME_ALREADY_EXISTS
) );
439 sText
.SearchAndReplaceAscii( "#" , m_sName
);
440 OSQLMessageBox
aDlg( getView(), String( ModuleRes( STR_ERROR_DURING_CREATION
) ), sText
, WB_OK
, OSQLMessageBox::Error
);
445 catch( const Exception
& )
448 DBG_UNHANDLED_EXCEPTION();
451 if ( aInfo
.isValid() )
452 aInfo
.prepend( String( ModuleRes( STR_TABLEDESIGN_SAVE_ERROR
) ) );
455 if (aInfo
.isValid() || bError
)
459 m_sName
= OUString();
460 stopTableListening();
464 return ! (aInfo
.isValid() || bError
);
467 // -----------------------------------------------------------------------------
468 void OTableController::doEditIndexes()
470 // table needs to be saved before editing indexes
471 if (m_bNew
|| isModified())
473 QueryBox
aAsk(getView(), ModuleRes(QUERY_SAVE_TABLE_EDIT_INDEXES
));
474 if (RET_YES
!= aAsk
.Execute())
477 if (!doSaveDoc(sal_False
))
480 OSL_ENSURE(!m_bNew
&& !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
483 Reference
< XNameAccess
> xIndexes
; // will be the keys of the table
484 Sequence
< OUString
> aFieldNames
; // will be the column names of the table
488 Reference
< XIndexesSupplier
> xIndexesSupp(m_xTable
, UNO_QUERY
);
489 if (xIndexesSupp
.is())
491 xIndexes
= xIndexesSupp
->getIndexes();
492 OSL_ENSURE(xIndexes
.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
495 OSL_FAIL("OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
497 // get the field names
498 Reference
< XColumnsSupplier
> xColSupp(m_xTable
, UNO_QUERY
);
499 OSL_ENSURE(xColSupp
.is(), "OTableController::doEditIndexes: no columns supplier!");
502 Reference
< XNameAccess
> xCols
= xColSupp
->getColumns();
503 OSL_ENSURE(xCols
.is(), "OTableController::doEditIndexes: no columns!");
505 aFieldNames
= xCols
->getElementNames();
508 catch( const Exception
& )
510 DBG_UNHANDLED_EXCEPTION();
516 DbaIndexDialog
aDialog(getView(), aFieldNames
, xIndexes
, getConnection(), getORB(), isConnected() ? getConnection()->getMetaData().is() && getConnection()->getMetaData()->getMaxColumnsInIndex() : sal_Int32(0));
517 if (RET_OK
!= aDialog
.Execute())
522 // -----------------------------------------------------------------------------
523 void OTableController::impl_initialize()
527 OTableController_BASE::impl_initialize();
529 const NamedValueCollection
& rArguments( getInitParams() );
531 rArguments
.get_ensureType( (OUString
)PROPERTY_CURRENTTABLE
, m_sName
);
533 // read autoincrement value set in the datasource
534 ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue
,m_sAutoIncrementValue
);
538 catch( const Exception
& )
540 DBG_UNHANDLED_EXCEPTION();
545 ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames
,m_aTypeInfo
,m_aTypeInfoIndex
); // fill the needed type information
547 catch(const SQLException
&)
549 OSQLWarningBox( getView(), ModuleRes( STR_NO_TYPE_INFO_AVAILABLE
) ).Execute();
554 loadData(); // fill the column information form the table
555 getView()->initialize(); // show the windows and fill with our information
557 setModified(sal_False
); // and we are not modified yet
559 catch( const Exception
& )
561 DBG_UNHANDLED_EXCEPTION();
564 // -----------------------------------------------------------------------------
565 sal_Bool
OTableController::Construct(Window
* pParent
)
567 setView( * new OTableDesignView( pParent
, getORB(), *this ) );
568 OTableController_BASE::Construct(pParent
);
571 // -----------------------------------------------------------------------------
572 sal_Bool SAL_CALL
OTableController::suspend(sal_Bool
/*_bSuspend*/) throw( RuntimeException
)
574 if ( getBroadcastHelper().bInDispose
|| getBroadcastHelper().bDisposed
)
577 SolarMutexGuard aSolarGuard
;
578 ::osl::MutexGuard
aGuard( getMutex() );
579 if ( getView() && getView()->IsInModalMode() )
582 static_cast<OTableDesignView
*>(getView())->GrabFocus();
583 sal_Bool bCheck
= sal_True
;
586 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
587 ::boost::mem_fn(&OTableRow::isValid
));
588 if ( aIter
!= m_vRowList
.end() )
590 QueryBox
aQry(getView(), ModuleRes(TABLE_DESIGN_SAVEMODIFIED
));
591 switch (aQry
.Execute())
594 Execute(ID_BROWSER_SAVEDOC
,Sequence
<PropertyValue
>());
596 bCheck
= sal_False
; // when we save the table this must be false else some press cancel
606 QueryBox
aQry(getView(), ModuleRes(TABLE_DESIGN_ALL_ROWS_DELETED
));
607 switch (aQry
.Execute())
613 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
614 Reference
<XNameAccess
> xTables
= xTablesSup
->getTables();
615 dropTable(xTables
,m_sName
);
617 catch(const Exception
&)
619 OSL_FAIL("OTableController::suspend: nothing is expected to happen here!");
634 // -----------------------------------------------------------------------------
635 void OTableController::describeSupportedFeatures()
637 OSingleDocumentController::describeSupportedFeatures();
639 implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO
, CommandGroup::EDIT
);
640 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC
, CommandGroup::EDIT
);
641 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO
, CommandGroup::EDIT
);
642 implDescribeSupportedFeature( ".uno:HelpMenu", SID_HELPMENU
, CommandGroup::APPLICATION
);
643 implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC
, CommandGroup::DOCUMENT
);
644 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
645 implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN
, CommandGroup::APPLICATION
);
646 implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC
, CommandGroup::EDIT
);
648 // -----------------------------------------------------------------------------
649 void OTableController::impl_onModifyChanged()
651 OSingleDocumentController::impl_onModifyChanged();
652 InvalidateFeature( SID_INDEXDESIGN
);
654 // -----------------------------------------------------------------------------
655 void SAL_CALL
OTableController::disposing( const EventObject
& _rSource
) throw(RuntimeException
)
657 if ( _rSource
.Source
== m_xTable
)
658 { // some deleted our table so we have a new one
659 stopTableListening();
662 setModified(sal_True
);
665 OTableController_BASE::disposing( _rSource
);
667 // -----------------------------------------------------------------------------
668 void OTableController::Save(const Reference
< XObjectOutputStream
>& _rxOut
)
670 OStreamSection
aSection(_rxOut
.get());
673 // -----------------------------------------------------------------------------
674 void OTableController::Load(const Reference
< XObjectInputStream
>& _rxIn
)
676 OStreamSection
aSection(_rxIn
.get());
679 // -----------------------------------------------------------------------------
680 void OTableController::losingConnection( )
682 // let the base class do it's reconnect
683 OTableController_BASE::losingConnection( );
685 // remove from the table
686 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
689 Reference
<XEventListener
> xEvtL( static_cast< ::cppu::OWeakObject
*>(this), UNO_QUERY
);
690 xComponent
->removeEventListener(xEvtL
);
692 stopTableListening();
698 setModified(sal_True
);
702 // -----------------------------------------------------------------------------
703 TOTypeInfoSP
OTableController::getTypeInfoByType(sal_Int32 _nDataType
) const
705 return queryTypeInfoByType(_nDataType
,m_aTypeInfo
);
707 // -----------------------------------------------------------------------------
708 void OTableController::appendColumns(Reference
<XColumnsSupplier
>& _rxColSup
,sal_Bool _bNew
,sal_Bool _bKeyColumns
)
712 // now append the columns
713 OSL_ENSURE(_rxColSup
.is(),"No columns supplier");
716 Reference
<XNameAccess
> xColumns
= _rxColSup
->getColumns();
717 OSL_ENSURE(xColumns
.is(),"No columns");
718 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
);
720 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
);
721 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
723 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
724 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
725 for(;aIter
!= aEnd
;++aIter
)
727 OSL_ENSURE(*aIter
,"OTableRow is null!");
728 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
729 if ( !pField
|| (!_bNew
&& (*aIter
)->IsReadOnly() && !_bKeyColumns
) )
732 Reference
<XPropertySet
> xColumn
;
733 if(pField
->IsPrimaryKey() || !_bKeyColumns
)
734 xColumn
= xColumnFactory
->createDataDescriptor();
738 ::dbaui::setColumnProperties(xColumn
,pField
);
740 xColumn
->setPropertyValue(PROPERTY_NAME
,makeAny(pField
->GetName()));
742 xAppend
->appendByDescriptor(xColumn
);
744 // now only the settings are missing
745 if(xColumns
->hasByName(pField
->GetName()))
747 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
749 pField
->copyColumnSettingsTo(xColumn
);
753 OSL_FAIL("OTableController::appendColumns: invalid field name!");
759 catch(const SQLException
& )
761 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
763 catch( const Exception
& )
765 DBG_UNHANDLED_EXCEPTION();
768 // -----------------------------------------------------------------------------
769 void OTableController::appendPrimaryKey(Reference
<XKeysSupplier
>& _rxSup
,sal_Bool _bNew
)
772 return; // the database doesn't support keys
774 OSL_ENSURE(_rxSup
.is(),"No XKeysSupplier!");
775 Reference
<XIndexAccess
> xKeys(_rxSup
->getKeys(),UNO_QUERY
);
776 Reference
<XPropertySet
> xProp
;
777 const sal_Int32 nCount
= xKeys
->getCount();
778 for(sal_Int32 i
=0;i
< nCount
;++i
)
780 xKeys
->getByIndex(i
) >>= xProp
;
781 sal_Int32 nKeyType
= 0;
782 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
783 if(KeyType::PRIMARY
== nKeyType
)
785 return; // primary key already exists after appending a column
788 Reference
<XDataDescriptorFactory
> xKeyFactory(xKeys
,UNO_QUERY
);
789 OSL_ENSURE(xKeyFactory
.is(),"No XDataDescriptorFactory Interface!");
790 if ( !xKeyFactory
.is() )
792 Reference
<XAppend
> xAppend(xKeyFactory
,UNO_QUERY
);
793 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
795 Reference
<XPropertySet
> xKey
= xKeyFactory
->createDataDescriptor();
796 OSL_ENSURE(xKey
.is(),"Key is null!");
797 xKey
->setPropertyValue(PROPERTY_TYPE
,makeAny(KeyType::PRIMARY
));
799 Reference
<XColumnsSupplier
> xColSup(xKey
,UNO_QUERY
);
802 appendColumns(xColSup
,_bNew
,sal_True
);
803 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
804 if(xColumns
->hasElements())
805 xAppend
->appendByDescriptor(xKey
);
808 // -----------------------------------------------------------------------------
809 void OTableController::loadData()
811 //////////////////////////////////////////////////////////////////////
812 // Wenn Datenstruktur bereits vorhanden, Struktur leeren
815 ::boost::shared_ptr
<OTableRow
> pTabEdRow
;
816 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
817 //////////////////////////////////////////////////////////////////////
818 // Datenstruktur mit Daten aus DatenDefinitionsObjekt fuellen
819 if(m_xTable
.is() && xMetaData
.is())
821 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY
);
822 OSL_ENSURE(xColSup
.is(),"No XColumnsSupplier!");
823 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
824 OFieldDescription
* pActFieldDescr
= NULL
;
825 //////////////////////////////////////////////////////////////////////
827 // Bei Drop darf keine Zeile editierbar sein.
828 // Bei Add duerfen nur die leeren Zeilen editierbar sein.
829 // Bei Add und Drop koennen alle Zeilen editiert werden.
830 // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
831 sal_Bool bIsAlterAllowed
= isAlterAllowed();
832 Sequence
< OUString
> aColumns
= xColumns
->getElementNames();
833 const OUString
* pIter
= aColumns
.getConstArray();
834 const OUString
* pEnd
= pIter
+ aColumns
.getLength();
836 for(;pIter
!= pEnd
;++pIter
)
838 Reference
<XPropertySet
> xColumn
;
839 xColumns
->getByName(*pIter
) >>= xColumn
;
841 sal_Int32 nScale
= 0;
842 sal_Int32 nPrecision
= 0;
843 sal_Int32 nNullable
= 0;
844 sal_Int32 nFormatKey
= 0;
845 sal_Int32 nAlign
= 0;
847 sal_Bool bIsAutoIncrement
= false, bIsCurrency
= false;
848 OUString sName
,sDescription
,sTypeName
,sHelpText
;
851 // get the properties from the column
852 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
853 xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
;
854 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
855 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bIsAutoIncrement
;
856 xColumn
->getPropertyValue(PROPERTY_ISCURRENCY
) >>= bIsCurrency
;
857 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
858 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
859 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
860 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
862 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT
))
863 xColumn
->getPropertyValue(PROPERTY_HELPTEXT
) >>= sHelpText
;
865 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
866 aControlDefault
= xColumn
->getPropertyValue(PROPERTY_CONTROLDEFAULT
);
867 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY
))
868 xColumn
->getPropertyValue(PROPERTY_FORMATKEY
) >>= nFormatKey
;
869 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN
))
870 xColumn
->getPropertyValue(PROPERTY_ALIGN
) >>= nAlign
;
872 pTabEdRow
.reset(new OTableRow());
873 pTabEdRow
->SetReadOnly(!bIsAlterAllowed
);
876 OUString
sCreate("x");
877 TOTypeInfoSP pTypeInfo
= ::dbaui::getTypeInfoFromType(m_aTypeInfo
,nType
,sTypeName
,sCreate
,nPrecision
,nScale
,bIsAutoIncrement
,bForce
);
878 if ( !pTypeInfo
.get() )
879 pTypeInfo
= m_pTypeInfo
;
880 pTabEdRow
->SetFieldType( pTypeInfo
, bForce
);
882 pActFieldDescr
= pTabEdRow
->GetActFieldDescr();
883 OSL_ENSURE(pActFieldDescr
, "OTableController::loadData: invalid field description generated by the table row!");
884 if ( pActFieldDescr
)
886 pActFieldDescr
->SetName(sName
);
887 pActFieldDescr
->SetFormatKey(nFormatKey
);
888 pActFieldDescr
->SetDescription(sDescription
);
889 pActFieldDescr
->SetHelpText(sHelpText
);
890 pActFieldDescr
->SetAutoIncrement(bIsAutoIncrement
);
891 pActFieldDescr
->SetHorJustify(dbaui::mapTextJustify(nAlign
));
892 pActFieldDescr
->SetCurrency(bIsCurrency
);
894 //////////////////////////////////////////////////////////////////////
896 pActFieldDescr
->SetIsNullable(nNullable
);
897 pActFieldDescr
->SetControlDefault(aControlDefault
);
898 pActFieldDescr
->SetPrecision(nPrecision
);
899 pActFieldDescr
->SetScale(nScale
);
901 m_vRowList
.push_back( pTabEdRow
);
903 // fill the primary key information
904 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
907 Sequence
< OUString
> aKeyColumns
= xKeyColumns
->getElementNames();
908 const OUString
* pKeyBegin
= aKeyColumns
.getConstArray();
909 const OUString
* pKeyEnd
= pKeyBegin
+ aKeyColumns
.getLength();
911 for(;pKeyBegin
!= pKeyEnd
;++pKeyBegin
)
913 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowIter
= m_vRowList
.begin();
914 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowEnd
= m_vRowList
.end();
915 for(;rowIter
!= rowEnd
;++rowIter
)
917 if((*rowIter
)->GetActFieldDescr()->GetName() == *pKeyBegin
)
919 (*rowIter
)->SetPrimaryKey(sal_True
);
927 //////////////////////////////////////////////////////////////////////
928 // Leere Zeilen fuellen
930 OTypeInfoMap::iterator aTypeIter
= m_aTypeInfo
.find(DataType::VARCHAR
);
931 if(aTypeIter
== m_aTypeInfo
.end())
932 aTypeIter
= m_aTypeInfo
.begin();
934 OSL_ENSURE(aTypeIter
!= m_aTypeInfo
.end(),"We have no type information!");
936 bool bReadRow
= !isAddAllowed();
937 for(sal_Int32 i
=m_vRowList
.size(); i
< NEWCOLS
; i
++ )
939 pTabEdRow
.reset(new OTableRow());
940 pTabEdRow
->SetReadOnly(bReadRow
);
941 m_vRowList
.push_back( pTabEdRow
);
944 // -----------------------------------------------------------------------------
945 Reference
<XNameAccess
> OTableController::getKeyColumns() const
947 return getPrimaryKeyColumns_throw(m_xTable
);
949 // -----------------------------------------------------------------------------
950 sal_Bool
OTableController::checkColumns(sal_Bool _bNew
) throw(::com::sun::star::sdbc::SQLException
)
952 sal_Bool bOk
= sal_True
;
953 sal_Bool bFoundPKey
= sal_False
;
954 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
955 DatabaseMetaData
aMetaData( getConnection() );
957 ::comphelper::UStringMixEqual
bCase(xMetaData
.is() ? xMetaData
->supportsMixedCaseQuotedIdentifiers() : sal_True
);
958 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
959 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
960 for(;aIter
!= aEnd
;++aIter
)
962 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
963 if (pFieldDesc
&& !pFieldDesc
->GetName().isEmpty())
965 bFoundPKey
|= (*aIter
)->IsPrimaryKey();
966 // first check for duplicate names
967 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter2
= aIter
+1;
968 for(;aIter2
!= aEnd
;++aIter2
)
970 OFieldDescription
* pCompareDesc
= (*aIter2
)->GetActFieldDescr();
971 if (pCompareDesc
&& bCase(pCompareDesc
->GetName(),pFieldDesc
->GetName()))
973 String strMessage
= String(ModuleRes(STR_TABLEDESIGN_DUPLICATE_NAME
));
974 strMessage
.SearchAndReplaceAscii("$column$", pFieldDesc
->GetName());
975 OSQLWarningBox( getView(), strMessage
).Execute();
981 if ( _bNew
&& !bFoundPKey
&& aMetaData
.supportsPrimaryKeys() )
983 String
sTitle(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD
));
984 String
sMsg(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY
));
985 OSQLMessageBox
aBox(getView(), sTitle
,sMsg
, WB_YES_NO_CANCEL
| WB_DEF_YES
);
987 switch ( aBox
.Execute() )
991 ::boost::shared_ptr
<OTableRow
> pNewRow(new OTableRow());
992 TOTypeInfoSP pTypeInfo
= ::dbaui::queryPrimaryKeyType(m_aTypeInfo
);
993 if ( !pTypeInfo
.get() )
996 pNewRow
->SetFieldType( pTypeInfo
);
997 OFieldDescription
* pActFieldDescr
= pNewRow
->GetActFieldDescr();
999 pActFieldDescr
->SetAutoIncrement(sal_False
);
1000 pActFieldDescr
->SetIsNullable(ColumnValue::NO_NULLS
);
1002 pActFieldDescr
->SetName( createUniqueName(OUString("ID") ));
1003 pActFieldDescr
->SetPrimaryKey( sal_True
);
1004 m_vRowList
.insert(m_vRowList
.begin(),pNewRow
);
1006 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->Invalidate();
1007 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->RowInserted(0);
1017 // -----------------------------------------------------------------------------
1018 void OTableController::alterColumns()
1020 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY_THROW
);
1021 OSL_ENSURE(xColSup
.is(),"What happen here?!");
1023 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
1024 Reference
<XIndexAccess
> xIdxColumns(xColumns
,UNO_QUERY_THROW
);
1025 OSL_ENSURE(xColumns
.is(),"No columns");
1026 if ( !xColumns
.is() )
1028 Reference
<XAlterTable
> xAlter(m_xTable
,UNO_QUERY
); // can be null
1030 sal_Int32 nColumnCount
= xIdxColumns
->getCount();
1031 Reference
<XDrop
> xDrop(xColumns
,UNO_QUERY
); // can be null
1032 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
); // can be null
1033 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
); // can be null
1035 sal_Bool bReload
= sal_False
; // refresh the data
1037 // contains all columns names which are already handled those which are not in the list will be deleted
1038 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1040 ::std::map
< OUString
,sal_Bool
,::comphelper::UStringMixLess
> aColumns(xMetaData
.is() ? (xMetaData
->supportsMixedCaseQuotedIdentifiers() ? true : false): sal_True
);
1041 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1042 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1043 // first look for columns where something other than the name changed
1045 for(;aIter
!= aEnd
;++aIter
,++nPos
)
1047 OSL_ENSURE(*aIter
,"OTableRow is null!");
1048 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1051 if ( (*aIter
)->IsReadOnly() )
1053 aColumns
[pField
->GetName()] = sal_True
;
1057 Reference
<XPropertySet
> xColumn
;
1058 if ( xColumns
->hasByName(pField
->GetName()) )
1060 aColumns
[pField
->GetName()] = sal_True
;
1061 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1062 OSL_ENSURE(xColumn
.is(),"Column is null!");
1064 sal_Int32 nType
=0,nPrecision
=0,nScale
=0,nNullable
=0;
1065 sal_Bool bAutoIncrement
= false;
1066 OUString sTypeName
,sDescription
;
1068 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1069 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
1070 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
1071 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
1072 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bAutoIncrement
;
1073 xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
) >>= sDescription
;
1075 try { xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
; }
1076 catch( const Exception
& )
1078 OSL_FAIL( "no TypeName property?!" );
1079 // since this is a last minute fix for #i41785#, I want to be on the safe side,
1080 // and catch errors here as early as possible (instead of the whole process of altering
1081 // the columns failing)
1082 // Normally, sdbcx::Column objects are expected to have a TypeName property
1085 // check if something changed
1086 if((nType
!= pField
->GetType() ||
1087 sTypeName
!= pField
->GetTypeName() ||
1088 (nPrecision
!= pField
->GetPrecision() && nPrecision
) ||
1089 nScale
!= pField
->GetScale() ||
1090 nNullable
!= pField
->GetIsNullable() ||
1091 sDescription
!= pField
->GetDescription() ||
1092 bAutoIncrement
!= pField
->IsAutoIncrement())&&
1093 xColumnFactory
.is())
1095 Reference
<XPropertySet
> xNewColumn
;
1096 xNewColumn
= xColumnFactory
->createDataDescriptor();
1097 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1098 // first try to alter the column
1099 sal_Bool bNotOk
= sal_False
;
1102 // first try if we can alter the column
1104 xAlter
->alterColumnByName(pField
->GetName(),xNewColumn
);
1106 catch(const SQLException
&)
1108 if(xDrop
.is() && xAppend
.is())
1110 String
aMessage( ModuleRes( STR_TABLEDESIGN_ALTER_ERROR
) );
1111 aMessage
.SearchAndReplaceAscii( "$column$", pField
->GetName() );
1113 SQLExceptionInfo
aError( ::cppu::getCaughtException() );
1114 OSQLWarningBox
aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
, &aError
);
1115 bNotOk
= aMsg
.Execute() == RET_YES
;
1120 // if something went wrong or we can't alter columns
1121 // drop and append a new one
1122 if((!xAlter
.is() || bNotOk
) && xDrop
.is() && xAppend
.is())
1124 xDrop
->dropByName(pField
->GetName());
1127 xAppend
->appendByDescriptor(xNewColumn
);
1129 catch(const SQLException
&)
1130 { // an error occurred so we try to reactivate the old one
1131 xAppend
->appendByDescriptor(xColumn
);
1135 // exceptions are caught outside
1137 if(xColumns
->hasByName(pField
->GetName()))
1138 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1144 else if(xColumnFactory
.is() && xAlter
.is() && nPos
< nColumnCount
)
1145 { // we can't find the column so we could try it with the index before we drop and append a new column
1148 Reference
<XPropertySet
> xNewColumn
;
1149 xNewColumn
= xColumnFactory
->createDataDescriptor();
1150 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1151 xAlter
->alterColumnByIndex(nPos
,xNewColumn
);
1152 if(xColumns
->hasByName(pField
->GetName()))
1153 { // ask for the append by name
1154 aColumns
[pField
->GetName()] = sal_True
;
1155 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1157 pField
->copyColumnSettingsTo(xColumn
);
1161 OSL_FAIL("OTableController::alterColumns: invalid column (2)!");
1164 catch(const SQLException
&)
1165 { // we couldn't alter the column so we have to add new columns
1167 if(xDrop
.is() && xAppend
.is())
1169 String
aMessage(ModuleRes(STR_TABLEDESIGN_ALTER_ERROR
));
1170 aMessage
.SearchAndReplaceAscii("$column$",pField
->GetName());
1171 OSQLWarningBox
aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
);
1172 if ( aMsg
.Execute() != RET_YES
)
1174 Reference
<XPropertySet
> xNewColumn(xIdxColumns
->getByIndex(nPos
),UNO_QUERY_THROW
);
1176 xNewColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
1177 aColumns
[sName
] = sal_True
;
1178 aColumns
[pField
->GetName()] = sal_True
;
1189 // alter column settings
1190 aIter
= m_vRowList
.begin();
1192 // first look for columns where something other than the name changed
1193 for(nPos
= 0;aIter
!= aEnd
;++aIter
,++nPos
)
1195 OSL_ENSURE(*aIter
,"OTableRow is null!");
1196 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1199 if ( (*aIter
)->IsReadOnly() )
1201 aColumns
[pField
->GetName()] = sal_True
;
1205 Reference
<XPropertySet
> xColumn
;
1206 if ( xColumns
->hasByName(pField
->GetName()) )
1208 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1209 Reference
<XPropertySetInfo
> xInfo
= xColumn
->getPropertySetInfo();
1210 if ( xInfo
->hasPropertyByName(PROPERTY_HELPTEXT
) )
1211 xColumn
->setPropertyValue(PROPERTY_HELPTEXT
,makeAny(pField
->GetHelpText()));
1213 if(xInfo
->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
1214 xColumn
->setPropertyValue(PROPERTY_CONTROLDEFAULT
,pField
->GetControlDefault());
1215 if(xInfo
->hasPropertyByName(PROPERTY_FORMATKEY
))
1216 xColumn
->setPropertyValue(PROPERTY_FORMATKEY
,makeAny(pField
->GetFormatKey()));
1217 if(xInfo
->hasPropertyByName(PROPERTY_ALIGN
))
1218 xColumn
->setPropertyValue(PROPERTY_ALIGN
,makeAny(dbaui::mapTextAllign(pField
->GetHorJustify())));
1221 // second drop all columns which could be found by name
1222 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
1223 // now we have to look for the columns who could be deleted
1226 Sequence
< OUString
> aColumnNames
= xColumns
->getElementNames();
1227 const OUString
* pIter
= aColumnNames
.getConstArray();
1228 const OUString
* pEnd
= pIter
+ aColumnNames
.getLength();
1229 for(;pIter
!= pEnd
;++pIter
)
1231 if(aColumns
.find(*pIter
) == aColumns
.end()) // found a column to delete
1233 if(xKeyColumns
.is() && xKeyColumns
->hasByName(*pIter
)) // check if this column is a member of the primary key
1235 String
aMsgT(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN
));
1236 aMsgT
.SearchAndReplaceAscii("$column$",*pIter
);
1237 String
aTitle(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE
));
1238 OSQLMessageBox
aMsg(getView(),aTitle
,aMsgT
,WB_YES_NO
| WB_DEF_YES
);
1239 if(aMsg
.Execute() == RET_YES
)
1252 xDrop
->dropByName(*pIter
);
1254 catch (const SQLException
&)
1256 String
sError( ModuleRes( STR_TABLEDESIGN_COULD_NOT_DROP_COL
) );
1257 sError
.SearchAndReplaceAscii( "$column$", *pIter
);
1259 SQLException aNewException
;
1260 aNewException
.Message
= sError
;
1261 aNewException
.SQLState
= OUString("S1000");
1262 aNewException
.NextException
= ::cppu::getCaughtException();
1264 throw aNewException
;
1270 // third append the new columns
1271 aIter
= m_vRowList
.begin();
1272 for(;aIter
!= aEnd
;++aIter
)
1274 OSL_ENSURE(*aIter
,"OTableRow is null!");
1275 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1276 if ( !pField
|| (*aIter
)->IsReadOnly() || aColumns
.find(pField
->GetName()) != aColumns
.end() )
1279 Reference
<XPropertySet
> xColumn
;
1280 if(!xColumns
->hasByName(pField
->GetName()))
1282 if(xColumnFactory
.is() && xAppend
.is())
1283 {// column not found by its name so we assume it is new
1285 xColumn
= xColumnFactory
->createDataDescriptor();
1286 ::dbaui::setColumnProperties(xColumn
,pField
);
1287 xAppend
->appendByDescriptor(xColumn
);
1288 if(xColumns
->hasByName(pField
->GetName()))
1289 { // ask for the append by name
1290 aColumns
[pField
->GetName()] = sal_True
;
1291 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1293 pField
->copyColumnSettingsTo(xColumn
);
1297 OSL_FAIL("OTableController::alterColumns: invalid column!");
1304 // check if we have to do something with the primary key
1305 sal_Bool bNeedDropKey
= sal_False
;
1306 sal_Bool bNeedAppendKey
= sal_False
;
1307 if ( xKeyColumns
.is() )
1309 aIter
= m_vRowList
.begin();
1310 for(;aIter
!= aEnd
;++aIter
)
1312 OSL_ENSURE(*aIter
,"OTableRow is null!");
1313 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1317 if ( pField
->IsPrimaryKey()
1318 && !xKeyColumns
->hasByName( pField
->GetName() )
1320 { // new primary key column inserted which isn't already in the columns selection
1321 bNeedDropKey
= bNeedAppendKey
= sal_True
;
1324 else if ( !pField
->IsPrimaryKey()
1325 && xKeyColumns
->hasByName( pField
->GetName() )
1327 { // found a column which currently is in the primary key, but is marked not to be anymore
1328 bNeedDropKey
= bNeedAppendKey
= sal_True
;
1334 { // no primary key available so we check if we should create one
1335 bNeedAppendKey
= sal_True
;
1338 if ( bNeedDropKey
&& xKeyColumns
.is() && xKeyColumns
->getElementNames().getLength() )
1341 if ( bNeedAppendKey
)
1343 Reference
< XKeysSupplier
> xKeySup( m_xTable
, UNO_QUERY
);
1344 appendPrimaryKey( xKeySup
,sal_False
);
1352 // -----------------------------------------------------------------------------
1353 void OTableController::dropPrimaryKey()
1355 SQLExceptionInfo aInfo
;
1358 Reference
<XKeysSupplier
> xKeySup(m_xTable
,UNO_QUERY
);
1359 Reference
<XIndexAccess
> xKeys
;
1361 xKeys
= xKeySup
->getKeys();
1365 Reference
<XPropertySet
> xProp
;
1366 for(sal_Int32 i
=0;i
< xKeys
->getCount();++i
)
1368 xProp
.set(xKeys
->getByIndex(i
),UNO_QUERY
);
1369 sal_Int32 nKeyType
= 0;
1370 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
1371 if(KeyType::PRIMARY
== nKeyType
)
1373 Reference
<XDrop
> xDrop(xKeys
,UNO_QUERY
);
1374 xDrop
->dropByIndex(i
); // delete the key
1380 catch(const SQLContext
& e
)
1382 aInfo
= SQLExceptionInfo(e
);
1384 catch(const SQLWarning
& e
)
1386 aInfo
= SQLExceptionInfo(e
);
1388 catch(const SQLException
& e
)
1390 aInfo
= SQLExceptionInfo(e
);
1392 catch( const Exception
& )
1394 DBG_UNHANDLED_EXCEPTION();
1399 // -----------------------------------------------------------------------------
1400 void OTableController::assignTable()
1403 if(!m_sName
.isEmpty())
1405 Reference
<XNameAccess
> xNameAccess
;
1406 Reference
<XTablesSupplier
> xSup(getConnection(),UNO_QUERY
);
1409 xNameAccess
= xSup
->getTables();
1410 OSL_ENSURE(xNameAccess
.is(),"no nameaccess for the queries!");
1412 Reference
<XPropertySet
> xProp
;
1413 if(xNameAccess
->hasByName(m_sName
) && ::cppu::extractInterface(xProp
,xNameAccess
->getByName(m_sName
)) && xProp
.is())
1416 startTableListening();
1418 // check if we set the table editable
1419 Reference
<XDatabaseMetaData
> xMeta
= getConnection()->getMetaData();
1420 setEditable( xMeta
.is() && !xMeta
->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1423 ::std::for_each(m_vRowList
.begin(),m_vRowList
.end(),boost::bind( &OTableRow::SetReadOnly
, _1
, boost::cref( sal_True
)));
1426 // be notified when the table is in disposing
1432 // -----------------------------------------------------------------------------
1433 sal_Bool
OTableController::isAddAllowed() const
1435 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1436 sal_Bool bAddAllowed
= !m_xTable
.is();
1438 bAddAllowed
= Reference
<XAppend
>(xColsSup
->getColumns(),UNO_QUERY
).is();
1442 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1443 bAddAllowed
= bAddAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithAddColumn());
1447 DBG_UNHANDLED_EXCEPTION();
1448 bAddAllowed
= sal_False
;
1453 // -----------------------------------------------------------------------------
1454 sal_Bool
OTableController::isDropAllowed() const
1456 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1457 sal_Bool bDropAllowed
= !m_xTable
.is();
1460 Reference
<XNameAccess
> xNameAccess
= xColsSup
->getColumns();
1461 bDropAllowed
= Reference
<XDrop
>(xNameAccess
,UNO_QUERY
).is() && xNameAccess
->hasElements();
1464 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1465 bDropAllowed
= bDropAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithDropColumn());
1467 return bDropAllowed
;
1469 // -----------------------------------------------------------------------------
1470 sal_Bool
OTableController::isAlterAllowed() const
1472 sal_Bool
bAllowed(!m_xTable
.is() || Reference
<XAlterTable
>(m_xTable
,UNO_QUERY
).is());
1475 // -----------------------------------------------------------------------------
1476 void OTableController::reSyncRows()
1478 sal_Bool bAlterAllowed
= isAlterAllowed();
1479 sal_Bool bAddAllowed
= isAddAllowed();
1480 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1481 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1482 for(;aIter
!= aEnd
;++aIter
)
1484 OSL_ENSURE(*aIter
,"OTableRow is null!");
1485 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1487 (*aIter
)->SetReadOnly(!bAlterAllowed
);
1489 (*aIter
)->SetReadOnly(!bAddAllowed
);
1492 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1495 setModified(sal_False
); // and we are not modified yet
1497 // -----------------------------------------------------------------------------
1498 OUString
OTableController::createUniqueName(const OUString
& _rName
)
1500 OUString sName
= _rName
;
1501 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1503 ::comphelper::UStringMixEqual
bCase(xMetaData
.is() ? xMetaData
->supportsMixedCaseQuotedIdentifiers() : sal_True
);
1505 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1506 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1507 for(sal_Int32 i
=0;aIter
!= aEnd
;++aIter
)
1509 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
1510 if (pFieldDesc
&& !pFieldDesc
->GetName().isEmpty() && bCase(sName
,pFieldDesc
->GetName()))
1511 { // found a second name of _rName so we need another
1512 sName
= _rName
+ OUString::valueOf(++i
);
1513 aIter
= m_vRowList
.begin(); // and retry
1518 // -----------------------------------------------------------------------------
1519 OUString
OTableController::getPrivateTitle() const
1525 if ( !m_sName
.isEmpty() && getConnection().is() )
1527 if ( m_xTable
.is() )
1528 sTitle
= ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable
, ::dbtools::eInDataManipulation
, false, false, false );
1532 if ( sTitle
.isEmpty() )
1534 String aName
= String(ModuleRes(STR_TBL_TITLE
));
1535 sTitle
= aName
.GetToken(0,' ');
1536 sTitle
+= OUString::valueOf(getCurrentStartNumber());
1539 catch( const Exception
& )
1541 DBG_UNHANDLED_EXCEPTION();
1545 // -----------------------------------------------------------------------------
1546 void OTableController::reload()
1548 loadData(); // fill the column information form the table
1549 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our information
1551 setModified(sal_False
); // and we are not modified yet
1552 static_cast<OTableDesignView
*>(getView())->Invalidate();
1554 // -----------------------------------------------------------------------------
1555 sal_Int32
OTableController::getFirstEmptyRowPosition()
1557 sal_Int32 nRet
= -1;
1558 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1559 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1560 for(;aIter
!= aEnd
;++aIter
)
1562 if ( !*aIter
|| !(*aIter
)->GetActFieldDescr() || (*aIter
)->GetActFieldDescr()->GetName().isEmpty() )
1564 nRet
= aIter
- m_vRowList
.begin();
1570 bool bReadRow
= !isAddAllowed();
1571 ::boost::shared_ptr
<OTableRow
> pTabEdRow(new OTableRow());
1572 pTabEdRow
->SetReadOnly(bReadRow
);
1573 nRet
= m_vRowList
.size();
1574 m_vRowList
.push_back( pTabEdRow
);
1578 // -----------------------------------------------------------------------------
1579 bool OTableController::isAutoIncrementPrimaryKey() const
1581 return getSdbMetaData().isAutoIncrementPrimaryKey();
1583 // -----------------------------------------------------------------------------
1585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */