1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TableController.cxx,v $
10 * $Revision: 1.122.24.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
33 #ifndef DBUI_TABLECONTROLLER_HXX
34 #include "TableController.hxx"
37 #ifndef _DBAU_REGHELPER_HXX_
38 #include "dbu_reghelper.hxx"
41 #include <tools/string.hxx>
43 #include <tools/diagnose_ex.h>
45 #include <sfx2/sfxsids.hrc>
48 #include "dbu_tbl.hrc"
50 #ifndef DBACCESS_UI_BROWSER_ID_HXX
51 #include "browserids.hxx"
53 #ifndef _COMPHELPER_TYPES_HXX_
54 #include <comphelper/types.hxx>
56 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
57 #include "dbustrings.hrc"
59 #ifndef DBACCESS_SOURCE_UI_INC_DEFAULTOBJECTNAMECHECK_HXX
60 #include "defaultobjectnamecheck.hxx"
62 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
63 #include <connectivity/dbtools.hxx>
65 #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
66 #include <com/sun/star/frame/FrameSearchFlag.hpp>
68 #ifndef _COMPHELPER_EXTRACT_HXX_
69 #include <comphelper/extract.hxx>
71 #ifndef DBAUI_DLGSAVE_HXX
72 #include "dlgsave.hxx"
74 #ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
75 #include <com/sun/star/container/XChild.hpp>
77 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
78 #include <com/sun/star/container/XNameContainer.hpp>
80 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_
81 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
83 #ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
84 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
86 #ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_
87 #include <com/sun/star/sdbcx/KeyType.hpp>
89 #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_
90 #include <com/sun/star/sdbcx/XDrop.hpp>
92 #ifndef _COM_SUN_STAR_SDBCX_XALTERTABLE_HPP_
93 #include <com/sun/star/sdbcx/XAlterTable.hpp>
95 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_
96 #include <com/sun/star/sdbcx/XAppend.hpp>
98 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
99 #include <com/sun/star/sdb/SQLContext.hpp>
101 #ifndef _COM_SUN_STAR_SDBC_SQLWARNING_HPP_
102 #include <com/sun/star/sdbc/SQLWarning.hpp>
104 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
105 #include <com/sun/star/sdbc/ColumnValue.hpp>
107 #ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
108 #include <com/sun/star/sdbc/XRow.hpp>
110 #ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_
111 #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
113 #include <com/sun/star/frame/XTitleChangeListener.hpp>
114 #ifndef _DBHELPER_DBEXCEPTION_HXX_
115 #include <connectivity/dbexception.hxx>
117 #ifndef _COM_SUN_STAR_UI_XEXECUTABLEDIALOG_HPP_
118 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
120 #include <com/sun/star/frame/XUntitledNumbers.hpp>
121 #ifndef _COMPHELPER_STREAMSECTION_HXX_
122 #include <comphelper/streamsection.hxx>
124 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_
125 #include <com/sun/star/io/XActiveDataSource.hpp>
127 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
128 #include <com/sun/star/io/XActiveDataSink.hpp>
130 #ifndef DBAUI_TABLEDESIGNVIEW_HXX
131 #include "TableDesignView.hxx"
133 #ifndef _COM_SUN_STAR_SDB_COMMANDTYPE_HPP_
134 #include <com/sun/star/sdb/CommandType.hpp>
136 #ifndef DBAUI_FIELDDESCRIPTIONS_HXX
137 #include "FieldDescriptions.hxx"
139 #ifndef DBAUI_TABLEROW_HXX
140 #include "TableRow.hxx"
142 #ifndef DBAUI_TYPEINFO_HXX
143 #include "TypeInfo.hxx"
145 #ifndef DBAUI_TABLEEDITORCONTROL_HXX
146 #include "TEditControl.hxx"
148 #ifndef _DBAUI_SQLMESSAGE_HXX_
149 #include "sqlmessage.hxx"
151 #ifndef _SV_MSGBOX_HXX
152 #include <vcl/msgbox.hxx>
154 #ifndef _DBAUI_INDEXDIALOG_HXX_
155 #include "indexdialog.hxx"
157 #ifndef DBAUI_TOOLS_HXX
158 #include "UITools.hxx"
160 #ifndef DBAUI_TOOLS_HXX
161 #include "UITools.hxx"
163 #include <boost/mem_fn.hpp>
165 #ifndef _CPPUHELPER_EXC_HLP_HXX_
166 #include <cppuhelper/exc_hlp.hxx>
168 #include "dsmeta.hxx"
169 #include <boost/bind.hpp>
171 #include <functional>
173 extern "C" void SAL_CALL
createRegistryInfo_OTableControl()
175 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OTableController
> aAutoRegistration
;
178 using namespace ::com::sun::star
;
179 using namespace ::com::sun::star::uno
;
180 using namespace ::com::sun::star::io
;
181 using namespace ::com::sun::star::beans
;
182 using namespace ::com::sun::star::frame
;
183 using namespace ::com::sun::star::util
;
184 using namespace ::com::sun::star::lang
;
185 using namespace ::com::sun::star::container
;
186 using namespace ::com::sun::star::sdbcx
;
187 using namespace ::com::sun::star::sdbc
;
188 using namespace ::com::sun::star::sdb
;
189 using namespace ::com::sun::star::ui
;
190 using namespace ::com::sun::star::util
;
191 using namespace ::dbtools
;
192 using namespace ::dbaui
;
193 using namespace ::comphelper
;
197 void dropTable(const Reference
<XNameAccess
>& _rxTable
,const ::rtl::OUString
& _sTableName
)
199 if ( _rxTable
->hasByName(_sTableName
) )
201 Reference
<XDrop
> xNameCont(_rxTable
,UNO_QUERY
);
202 OSL_ENSURE(xNameCont
.is(),"No drop interface for tables!");
203 if ( xNameCont
.is() )
204 xNameCont
->dropByName(_sTableName
);
207 //------------------------------------------------------------------------------
208 struct OTableRowCompare
: public ::std::binary_function
< ::boost::shared_ptr
<OTableRow
> , ::rtl::OUString
, bool>
210 bool operator() (const ::boost::shared_ptr
<OTableRow
> lhs
, const ::rtl::OUString
& rhs
) const
212 OFieldDescription
* pField
= lhs
->GetActFieldDescr();
213 return pField
&& pField
->GetName() == rhs
;
219 //------------------------------------------------------------------------------
220 ::rtl::OUString SAL_CALL
OTableController::getImplementationName() throw( RuntimeException
)
222 return getImplementationName_Static();
225 //------------------------------------------------------------------------------
226 ::rtl::OUString
OTableController::getImplementationName_Static() throw( RuntimeException
)
228 return ::rtl::OUString::createFromAscii("org.openoffice.comp.dbu.OTableDesign");
230 //------------------------------------------------------------------------------
231 Sequence
< ::rtl::OUString
> OTableController::getSupportedServiceNames_Static(void) throw( RuntimeException
)
233 Sequence
< ::rtl::OUString
> aSupported(1);
234 aSupported
.getArray()[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.TableDesign");
237 //-------------------------------------------------------------------------
238 Sequence
< ::rtl::OUString
> SAL_CALL
OTableController::getSupportedServiceNames() throw(RuntimeException
)
240 return getSupportedServiceNames_Static();
242 // -------------------------------------------------------------------------
243 Reference
< XInterface
> SAL_CALL
OTableController::Create(const Reference
<XMultiServiceFactory
>& _rxFactory
)
245 return *(new OTableController(_rxFactory
));
248 DBG_NAME(OTableController
)
249 // -----------------------------------------------------------------------------
250 OTableController::OTableController(const Reference
< XMultiServiceFactory
>& _rM
) : OTableController_BASE(_rM
)
251 ,m_sTypeNames(ModuleRes(STR_TABLEDESIGN_DBFIELDTYPES
))
253 ,m_bAllowAutoIncrementValue(sal_False
)
256 DBG_CTOR(OTableController
,NULL
);
259 m_pTypeInfo
= TOTypeInfoSP(new OTypeInfo());
260 m_pTypeInfo
->aUIName
= m_sTypeNames
.GetToken(TYPE_OTHER
);
262 // -----------------------------------------------------------------------------
263 OTableController::~OTableController()
265 m_aTypeInfoIndex
.clear();
268 DBG_DTOR(OTableController
,NULL
);
271 // -----------------------------------------------------------------------------
272 void OTableController::startTableListening()
274 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
276 xComponent
->addEventListener(static_cast<XModifyListener
*>(this));
279 // -----------------------------------------------------------------------------
280 void OTableController::stopTableListening()
282 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
284 xComponent
->removeEventListener(static_cast<XModifyListener
*>(this));
287 // -----------------------------------------------------------------------------
288 void OTableController::disposing()
290 OTableController_BASE::disposing();
295 // -----------------------------------------------------------------------------
296 FeatureState
OTableController::GetState(sal_uInt16 _nId
) const
298 FeatureState aReturn
;
299 // (disabled automatically)
303 case ID_BROWSER_CLOSE
:
304 aReturn
.bEnabled
= sal_True
;
306 case ID_BROWSER_EDITDOC
:
307 aReturn
.bChecked
= isEditable();
308 aReturn
.bEnabled
= m_bNew
|| isEditable();// the editable flag is set through this one -> || isAddAllowed() || isDropAllowed() || isAlterAllowed();
310 case ID_BROWSER_SAVEDOC
:
311 aReturn
.bEnabled
= isModified();
312 if ( aReturn
.bEnabled
)
314 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
315 ::boost::mem_fn(&OTableRow::isValid
));
316 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
319 case ID_BROWSER_SAVEASDOC
:
320 aReturn
.bEnabled
= isConnected() && isEditable();
321 if ( aReturn
.bEnabled
)
323 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
324 ::boost::mem_fn(&OTableRow::isValid
));
325 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
330 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCutAllowed();
332 case ID_BROWSER_COPY
:
333 aReturn
.bEnabled
= m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isCopyAllowed();
335 case ID_BROWSER_PASTE
:
336 aReturn
.bEnabled
= isEditable() && m_aCurrentFrame
.isActive() && getView() && static_cast<OTableDesignView
*>(getView())->isPasteAllowed();
338 case SID_INDEXDESIGN
:
340 ( ( ((!m_bNew
&& isModified()) || isModified())
341 || Reference
< XIndexesSupplier
>(m_xTable
, UNO_QUERY
).is()
345 if ( aReturn
.bEnabled
)
347 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
348 ::boost::mem_fn(&OTableRow::isValid
));
349 aReturn
.bEnabled
= aIter
!= m_vRowList
.end();
353 aReturn
= OTableController_BASE::GetState(_nId
);
357 // -----------------------------------------------------------------------------
358 void OTableController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
362 case ID_BROWSER_EDITDOC
:
363 setEditable(!isEditable());
364 static_cast<OTableDesignView
*>(getView())->setReadOnly(!isEditable());
365 InvalidateFeature(ID_BROWSER_PASTE
);
366 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
368 case ID_BROWSER_SAVEASDOC
:
371 case ID_BROWSER_SAVEDOC
:
372 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->SaveCurRow();
373 doSaveDoc(sal_False
);
376 static_cast<OTableDesignView
*>(getView())->cut();
378 case ID_BROWSER_COPY
:
379 static_cast<OTableDesignView
*>(getView())->copy();
381 case ID_BROWSER_PASTE
:
382 static_cast<OTableDesignView
*>(getView())->paste();
384 case SID_INDEXDESIGN
:
388 OTableController_BASE::Execute(_nId
,aArgs
);
390 InvalidateFeature(_nId
);
393 // -----------------------------------------------------------------------------
394 sal_Bool
OTableController::doSaveDoc(sal_Bool _bSaveAs
)
397 reconnect(sal_True
); // ask the user for a new connection
398 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
400 if (!xTablesSup
.is())
402 String
aMessage(ModuleRes(STR_TABLEDESIGN_CONNECTION_MISSING
));
403 OSQLWarningBox( getView(), aMessage
).Execute();
407 // check if a column exists
410 Reference
<XNameAccess
> xTables
;
411 ::rtl::OUString sCatalog
, sSchema
;
413 sal_Bool bNew
= (0 == m_sName
.getLength());
414 bNew
= bNew
|| m_bNew
|| _bSaveAs
;
418 xTables
= xTablesSup
->getTables();
419 OSL_ENSURE(xTables
.is(),"The tables can't be null!");
420 bNew
= bNew
|| (xTables
.is() && !xTables
->hasByName(m_sName
));
422 // first we need a name for our query so ask the user
426 if (_bSaveAs
&& !bNew
)
427 aDefaultName
= String(m_sName
);
430 String aName
= String(ModuleRes(STR_TBL_TITLE
));
431 aDefaultName
= aName
.GetToken(0,' ');
432 //aDefaultName = getPrivateTitle();
433 aDefaultName
= ::dbtools::createUniqueName(xTables
,aDefaultName
);
436 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::TABLE
);
437 OSaveAsDlg
aDlg( getView(), CommandType::TABLE
, getORB(), getConnection(), aDefaultName
, aNameChecker
);
438 if ( aDlg
.Execute() != RET_OK
)
441 m_sName
= aDlg
.getName();
442 sCatalog
= aDlg
.getCatalog();
443 sSchema
= aDlg
.getSchema();
447 if(!m_sName
.getLength())
452 OSL_ENSURE(sal_False
, "OTableController::doSaveDoc: nothing is expected to happen here!");
455 sal_Bool bAlter
= sal_False
;
456 sal_Bool bError
= sal_False
;
457 SQLExceptionInfo aInfo
;
460 // check the columns for double names
461 if(!checkColumns(bNew
|| !xTables
->hasByName(m_sName
)))
467 Reference
<XPropertySet
> xTable
;
468 if(bNew
|| !xTables
->hasByName(m_sName
)) // just to make sure the table already exists
470 dropTable(xTables
,m_sName
);
472 Reference
<XDataDescriptorFactory
> xFact(xTables
,UNO_QUERY
);
473 OSL_ENSURE(xFact
.is(),"OTableController::doSaveDoc: No XDataDescriptorFactory available!");
474 xTable
= xFact
->createDataDescriptor();
475 OSL_ENSURE(xTable
.is(),"OTableController::doSaveDoc: Create query failed!");
476 // to set the name is only allowed when the wuery is new
477 xTable
->setPropertyValue(PROPERTY_CATALOGNAME
,makeAny(sCatalog
));
478 xTable
->setPropertyValue(PROPERTY_SCHEMANAME
,makeAny(sSchema
));
479 xTable
->setPropertyValue(PROPERTY_NAME
,makeAny(m_sName
));
481 // now append the columns
482 Reference
<XColumnsSupplier
> xColSup(xTable
,UNO_QUERY
);
483 appendColumns(xColSup
,bNew
);
484 // now append the primary key
485 Reference
<XKeysSupplier
> xKeySup(xTable
,UNO_QUERY
);
486 appendPrimaryKey(xKeySup
,bNew
);
488 // now set the properties
491 Reference
<XAppend
> xAppend(xTables
,UNO_QUERY
);
492 OSL_ENSURE(xAppend
.is(),"OTableController::doSaveDoc: No XAppend Interface!");
493 xAppend
->appendByDescriptor(xTable
);
496 if(!m_xTable
.is()) // correct name and try again
498 // it can be that someone inserted new data for us
499 m_sName
= ::dbtools::composeTableName( getConnection()->getMetaData(), xTable
, ::dbtools::eInDataManipulation
, false, false, false );
502 // now check if our datasource has set a tablefilter and if append the new table name to it
503 ::dbaui::appendToFilter(getConnection(),m_sName
,getORB(),getView()); // we are not interessted in the return value
504 Reference
< frame::XTitleChangeListener
> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY
);
505 if ( xEventListener
.is() )
507 frame::TitleChangedEvent aEvent
;
508 xEventListener
->titleChanged(aEvent
);
510 releaseNumberForComponent();
512 else if(m_xTable
.is())
519 catch(const SQLContext
& e
)
521 aInfo
= SQLExceptionInfo(e
);
523 catch(const SQLWarning
& e
)
525 aInfo
= SQLExceptionInfo(e
);
527 catch(const SQLException
& e
)
529 aInfo
= SQLExceptionInfo(e
);
531 catch(const ElementExistException
& )
533 String
sText( ModuleRes( STR_NAME_ALREADY_EXISTS
) );
534 sText
.SearchAndReplaceAscii( "#" , m_sName
);
535 OSQLMessageBox
aDlg( getView(), String( ModuleRes( STR_ERROR_DURING_CREATION
) ), sText
, WB_OK
, OSQLMessageBox::Error
);
540 catch( const Exception
& )
543 DBG_UNHANDLED_EXCEPTION();
546 if ( aInfo
.isValid() )
547 aInfo
.prepend( String( ModuleRes( STR_TABLEDESIGN_SAVE_ERROR
) ) );
550 if (aInfo
.isValid() || bError
)
554 m_sName
= ::rtl::OUString();
555 stopTableListening();
558 // reload(); // a error occured so we have to reload
560 return ! (aInfo
.isValid() || bError
);
563 // -----------------------------------------------------------------------------
564 void OTableController::doEditIndexes()
566 // table needs to be saved before editing indexes
567 if (m_bNew
|| isModified())
569 QueryBox
aAsk(getView(), ModuleRes(QUERY_SAVE_TABLE_EDIT_INDEXES
));
570 if (RET_YES
!= aAsk
.Execute())
573 if (!doSaveDoc(sal_False
))
576 OSL_ENSURE(!m_bNew
&& !isModified(), "OTableController::doEditIndexes: what the hell did doSaveDoc do?");
579 Reference
< XNameAccess
> xIndexes
; // will be the keys of the table
580 Sequence
< ::rtl::OUString
> aFieldNames
; // will be the column names of the table
584 Reference
< XIndexesSupplier
> xIndexesSupp(m_xTable
, UNO_QUERY
);
585 if (xIndexesSupp
.is())
587 xIndexes
= xIndexesSupp
->getIndexes();
588 OSL_ENSURE(xIndexes
.is(), "OTableController::doEditIndexes: no keys got from the indexes supplier!");
591 OSL_ENSURE(sal_False
, "OTableController::doEditIndexes: should never have reached this (no indexes supplier)!");
593 // get the field names
594 Reference
< XColumnsSupplier
> xColSupp(m_xTable
, UNO_QUERY
);
595 OSL_ENSURE(xColSupp
.is(), "OTableController::doEditIndexes: no columns supplier!");
598 Reference
< XNameAccess
> xCols
= xColSupp
->getColumns();
599 OSL_ENSURE(xCols
.is(), "OTableController::doEditIndexes: no columns!");
601 aFieldNames
= xCols
->getElementNames();
604 catch( const Exception
& )
606 DBG_UNHANDLED_EXCEPTION();
612 DbaIndexDialog
aDialog(getView(), aFieldNames
, xIndexes
, getConnection(),getORB(),isConnected() ? getConnection()->getMetaData().is() && getConnection()->getMetaData()->getMaxColumnsInIndex() : sal_Int32(0));
613 if (RET_OK
!= aDialog
.Execute())
618 // -----------------------------------------------------------------------------
619 void OTableController::impl_initialize()
623 OTableController_BASE::impl_initialize();
625 const NamedValueCollection
& rArguments( getInitParams() );
627 rArguments
.get_ensureType( (::rtl::OUString
)PROPERTY_CURRENTTABLE
, m_sName
);
629 // read autoincrement value set in the datasource
630 ::dbaui::fillAutoIncrementValue(getDataSource(),m_bAllowAutoIncrementValue
,m_sAutoIncrementValue
);
634 catch( const Exception
& )
636 DBG_UNHANDLED_EXCEPTION();
641 ::dbaui::fillTypeInfo(getConnection(),m_sTypeNames
,m_aTypeInfo
,m_aTypeInfoIndex
); // fill the needed type information
643 catch(const SQLException
&)
645 OSQLWarningBox( getView(), ModuleRes( STR_NO_TYPE_INFO_AVAILABLE
) ).Execute();
650 loadData(); // fill the column information form the table
651 getView()->initialize(); // show the windows and fill with our informations
652 getUndoMgr()->Clear(); // clear all undo redo things
653 setModified(sal_False
); // and we are not modified yet
655 catch( const Exception
& )
657 DBG_UNHANDLED_EXCEPTION();
660 // -----------------------------------------------------------------------------
661 sal_Bool
OTableController::Construct(Window
* pParent
)
663 m_pView
= new OTableDesignView( pParent
, getORB(), *this );
664 OTableController_BASE::Construct(pParent
);
665 // m_pView->Construct();
669 // -----------------------------------------------------------------------------
670 sal_Bool SAL_CALL
OTableController::suspend(sal_Bool
/*_bSuspend*/) throw( RuntimeException
)
672 if ( getBroadcastHelper().bInDispose
|| getBroadcastHelper().bDisposed
)
675 vos::OGuard
aSolarGuard( Application::GetSolarMutex() );
676 ::osl::MutexGuard
aGuard( getMutex() );
677 if ( getView() && getView()->IsInModalMode() )
680 static_cast<OTableDesignView
*>(getView())->GrabFocus();
681 sal_Bool bCheck
= sal_True
;
684 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= ::std::find_if(m_vRowList
.begin(),m_vRowList
.end(),
685 ::boost::mem_fn(&OTableRow::isValid
));
686 if ( aIter
!= m_vRowList
.end() )
688 QueryBox
aQry(getView(), ModuleRes(TABLE_DESIGN_SAVEMODIFIED
));
689 switch (aQry
.Execute())
692 Execute(ID_BROWSER_SAVEDOC
,Sequence
<PropertyValue
>());
694 bCheck
= sal_False
; // when we save the table this must be false else some press cancel
704 QueryBox
aQry(getView(), ModuleRes(TABLE_DESIGN_ALL_ROWS_DELETED
));
705 switch (aQry
.Execute())
711 Reference
<XTablesSupplier
> xTablesSup(getConnection(),UNO_QUERY
);
712 Reference
<XNameAccess
> xTables
= xTablesSup
->getTables();
713 dropTable(xTables
,m_sName
);
715 catch(const Exception
&)
717 OSL_ENSURE(sal_False
, "OTableController::suspend: nothing is expected to happen here!");
731 OSingleDocumentController::suspend(_bSuspend);
735 // -----------------------------------------------------------------------------
736 void OTableController::describeSupportedFeatures()
738 OSingleDocumentController::describeSupportedFeatures();
740 implDescribeSupportedFeature( ".uno:Redo", ID_BROWSER_REDO
, CommandGroup::EDIT
);
741 implDescribeSupportedFeature( ".uno:Save", ID_BROWSER_SAVEDOC
, CommandGroup::EDIT
);
742 implDescribeSupportedFeature( ".uno:Undo", ID_BROWSER_UNDO
, CommandGroup::EDIT
);
743 implDescribeSupportedFeature( ".uno:HelpMenu", SID_HELPMENU
, CommandGroup::APPLICATION
);
744 implDescribeSupportedFeature( ".uno:NewDoc", SID_NEWDOC
, CommandGroup::DOCUMENT
);
745 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
746 implDescribeSupportedFeature( ".uno:DBIndexDesign", SID_INDEXDESIGN
, CommandGroup::APPLICATION
);
747 implDescribeSupportedFeature( ".uno:EditDoc", ID_BROWSER_EDITDOC
, CommandGroup::EDIT
);
749 // -----------------------------------------------------------------------------
750 SfxUndoManager
* OTableController::getUndoMgr()
752 return &m_aUndoManager
;
754 // -----------------------------------------------------------------------------
755 void OTableController::setModified(sal_Bool _bModified
)
757 OSingleDocumentController::setModified(_bModified
);
758 InvalidateFeature(SID_INDEXDESIGN
);
760 // -----------------------------------------------------------------------------
761 void SAL_CALL
OTableController::disposing( const EventObject
& _rSource
) throw(RuntimeException
)
763 if ( _rSource
.Source
== m_xTable
)
764 { // some deleted our table so we have a new one
765 stopTableListening();
768 setModified(sal_True
);
771 OTableController_BASE::disposing( _rSource
);
773 // -----------------------------------------------------------------------------
774 void OTableController::Save(const Reference
< XObjectOutputStream
>& _rxOut
)
776 OStreamSection
aSection(_rxOut
.get());
779 // -----------------------------------------------------------------------------
780 void OTableController::Load(const Reference
< XObjectInputStream
>& _rxIn
)
782 OStreamSection
aSection(_rxIn
.get());
785 // -----------------------------------------------------------------------------
786 void OTableController::losingConnection( )
788 // let the base class do it's reconnect
789 OTableController_BASE::losingConnection( );
791 // remove from the table
792 Reference
< XComponent
> xComponent(m_xTable
, UNO_QUERY
);
795 Reference
<XEventListener
> xEvtL( static_cast< ::cppu::OWeakObject
*>(this), UNO_QUERY
);
796 xComponent
->removeEventListener(xEvtL
);
798 stopTableListening();
804 setModified(sal_True
);
808 // -----------------------------------------------------------------------------
809 TOTypeInfoSP
OTableController::getTypeInfoByType(sal_Int32 _nDataType
) const
811 return queryTypeInfoByType(_nDataType
,m_aTypeInfo
);
813 // -----------------------------------------------------------------------------
814 void OTableController::appendColumns(Reference
<XColumnsSupplier
>& _rxColSup
,sal_Bool _bNew
,sal_Bool _bKeyColumns
)
818 // now append the columns
819 OSL_ENSURE(_rxColSup
.is(),"No columns supplier");
822 Reference
<XNameAccess
> xColumns
= _rxColSup
->getColumns();
823 OSL_ENSURE(xColumns
.is(),"No columns");
824 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
);
826 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
);
827 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
829 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
830 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
831 for(;aIter
!= aEnd
;++aIter
)
833 OSL_ENSURE(*aIter
,"OTableRow is null!");
834 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
835 if ( !pField
|| (!_bNew
&& (*aIter
)->IsReadOnly() && !_bKeyColumns
) )
838 Reference
<XPropertySet
> xColumn
;
839 if(pField
->IsPrimaryKey() || !_bKeyColumns
)
840 xColumn
= xColumnFactory
->createDataDescriptor();
844 ::dbaui::setColumnProperties(xColumn
,pField
);
846 xColumn
->setPropertyValue(PROPERTY_NAME
,makeAny(pField
->GetName()));
848 xAppend
->appendByDescriptor(xColumn
);
850 // now only the settings are missing
851 if(xColumns
->hasByName(pField
->GetName()))
853 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
855 pField
->copyColumnSettingsTo(xColumn
);
859 OSL_ENSURE(sal_False
, "OTableController::appendColumns: invalid field name!");
865 catch(const SQLException
& )
867 showError( SQLExceptionInfo( ::cppu::getCaughtException() ) );
869 catch( const Exception
& )
871 DBG_UNHANDLED_EXCEPTION();
874 // -----------------------------------------------------------------------------
875 void OTableController::appendPrimaryKey(Reference
<XKeysSupplier
>& _rxSup
,sal_Bool _bNew
)
878 return; // the database doesn't support keys
880 OSL_ENSURE(_rxSup
.is(),"No XKeysSupplier!");
881 Reference
<XIndexAccess
> xKeys(_rxSup
->getKeys(),UNO_QUERY
);
882 Reference
<XPropertySet
> xProp
;
883 const sal_Int32 nCount
= xKeys
->getCount();
884 for(sal_Int32 i
=0;i
< nCount
;++i
)
886 xKeys
->getByIndex(i
) >>= xProp
;
887 sal_Int32 nKeyType
= 0;
888 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
889 if(KeyType::PRIMARY
== nKeyType
)
891 return; // primary key already exists after appending a column
894 Reference
<XDataDescriptorFactory
> xKeyFactory(xKeys
,UNO_QUERY
);
895 OSL_ENSURE(xKeyFactory
.is(),"No XDataDescriptorFactory Interface!");
896 if ( !xKeyFactory
.is() )
898 Reference
<XAppend
> xAppend(xKeyFactory
,UNO_QUERY
);
899 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
901 Reference
<XPropertySet
> xKey
= xKeyFactory
->createDataDescriptor();
902 OSL_ENSURE(xKey
.is(),"Key is null!");
903 xKey
->setPropertyValue(PROPERTY_TYPE
,makeAny(KeyType::PRIMARY
));
905 Reference
<XColumnsSupplier
> xColSup(xKey
,UNO_QUERY
);
908 appendColumns(xColSup
,_bNew
,sal_True
);
909 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
910 if(xColumns
->hasElements())
911 xAppend
->appendByDescriptor(xKey
);
914 // -----------------------------------------------------------------------------
915 void OTableController::loadData()
917 //////////////////////////////////////////////////////////////////////
918 // Wenn Datenstruktur bereits vorhanden, Struktur leeren
921 ::boost::shared_ptr
<OTableRow
> pTabEdRow
;
922 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
923 //////////////////////////////////////////////////////////////////////
924 // Datenstruktur mit Daten aus DatenDefinitionsObjekt fuellen
925 if(m_xTable
.is() && xMetaData
.is())
927 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY
);
928 OSL_ENSURE(xColSup
.is(),"No XColumnsSupplier!");
929 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
930 OFieldDescription
* pActFieldDescr
= NULL
;
932 //////////////////////////////////////////////////////////////////////
934 // Bei Drop darf keine Zeile editierbar sein.
935 // Bei Add duerfen nur die leeren Zeilen editierbar sein.
936 // Bei Add und Drop koennen alle Zeilen editiert werden.
937 // sal_Bool bReadOldRow = xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn();
938 sal_Bool bIsAlterAllowed
= isAlterAllowed();
939 Sequence
< ::rtl::OUString
> aColumns
= xColumns
->getElementNames();
940 const ::rtl::OUString
* pIter
= aColumns
.getConstArray();
941 const ::rtl::OUString
* pEnd
= pIter
+ aColumns
.getLength();
943 for(;pIter
!= pEnd
;++pIter
)
945 Reference
<XPropertySet
> xColumn
;
946 xColumns
->getByName(*pIter
) >>= xColumn
;
948 sal_Int32 nScale
= 0;
949 sal_Int32 nPrecision
= 0;
950 sal_Int32 nNullable
= 0;
951 sal_Int32 nFormatKey
= 0;
952 sal_Int32 nAlign
= 0;
954 sal_Bool bIsAutoIncrement
= false, bIsCurrency
= false;
955 ::rtl::OUString sName
,sDescription
,sTypeName
;
958 // get the properties from the column
959 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
960 xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
;
961 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
962 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bIsAutoIncrement
;
963 xColumn
->getPropertyValue(PROPERTY_ISCURRENCY
) >>= bIsCurrency
;
964 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
965 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
966 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
969 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_HELPTEXT
))
970 xColumn
->getPropertyValue(PROPERTY_HELPTEXT
) >>= sDescription
;
971 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
972 aControlDefault
= xColumn
->getPropertyValue(PROPERTY_CONTROLDEFAULT
);
973 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_FORMATKEY
))
974 xColumn
->getPropertyValue(PROPERTY_FORMATKEY
) >>= nFormatKey
;
975 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_ALIGN
))
976 xColumn
->getPropertyValue(PROPERTY_ALIGN
) >>= nAlign
;
978 pTabEdRow
.reset(new OTableRow());
979 pTabEdRow
->SetReadOnly(!bIsAlterAllowed
);
982 ::rtl::OUString
sCreate(RTL_CONSTASCII_USTRINGPARAM("x"));
983 TOTypeInfoSP pTypeInfo
= ::dbaui::getTypeInfoFromType(m_aTypeInfo
,nType
,sTypeName
,sCreate
,nPrecision
,nScale
,bIsAutoIncrement
,bForce
);
984 if ( !pTypeInfo
.get() )
985 pTypeInfo
= m_pTypeInfo
;
986 pTabEdRow
->SetFieldType( pTypeInfo
, bForce
);
988 pActFieldDescr
= pTabEdRow
->GetActFieldDescr();
989 OSL_ENSURE(pActFieldDescr
, "OTableController::loadData: invalid field description generated by the table row!");
990 if ( pActFieldDescr
)
992 pActFieldDescr
->SetName(sName
);
993 pActFieldDescr
->SetFormatKey(nFormatKey
);
994 // pActFieldDescr->SetPrimaryKey(pPrimary->GetValue());
995 pActFieldDescr
->SetDescription(sDescription
);
996 pActFieldDescr
->SetAutoIncrement(bIsAutoIncrement
);
997 pActFieldDescr
->SetHorJustify(dbaui::mapTextJustify(nAlign
));
998 pActFieldDescr
->SetCurrency(bIsCurrency
);
1000 //////////////////////////////////////////////////////////////////////
1002 pActFieldDescr
->SetIsNullable(nNullable
);
1003 pActFieldDescr
->SetControlDefault(aControlDefault
);
1004 pActFieldDescr
->SetPrecision(nPrecision
);
1005 pActFieldDescr
->SetScale(nScale
);
1007 m_vRowList
.push_back( pTabEdRow
);
1009 // fill the primary key information
1010 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
1011 if(xKeyColumns
.is())
1013 Sequence
< ::rtl::OUString
> aKeyColumns
= xKeyColumns
->getElementNames();
1014 const ::rtl::OUString
* pKeyBegin
= aKeyColumns
.getConstArray();
1015 const ::rtl::OUString
* pKeyEnd
= pKeyBegin
+ aKeyColumns
.getLength();
1017 for(;pKeyBegin
!= pKeyEnd
;++pKeyBegin
)
1019 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowIter
= m_vRowList
.begin();
1020 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator rowEnd
= m_vRowList
.end();
1021 for(;rowIter
!= rowEnd
;++rowIter
)
1023 if((*rowIter
)->GetActFieldDescr()->GetName() == *pKeyBegin
)
1025 (*rowIter
)->SetPrimaryKey(sal_True
);
1033 //////////////////////////////////////////////////////////////////////
1034 // Leere Zeilen fuellen
1036 OTypeInfoMap::iterator aTypeIter
= m_aTypeInfo
.find(DataType::VARCHAR
);
1037 if(aTypeIter
== m_aTypeInfo
.end())
1038 aTypeIter
= m_aTypeInfo
.begin();
1040 OSL_ENSURE(aTypeIter
!= m_aTypeInfo
.end(),"We have no type infomation!");
1042 bool bReadRow
= !isAddAllowed();
1043 for(sal_Int32 i
=m_vRowList
.size(); i
<128; i
++ )
1045 pTabEdRow
.reset(new OTableRow());
1046 pTabEdRow
->SetReadOnly(bReadRow
);
1047 m_vRowList
.push_back( pTabEdRow
);
1050 // -----------------------------------------------------------------------------
1051 Reference
<XNameAccess
> OTableController::getKeyColumns() const
1053 // use keys and indexes for excat postioning
1055 Reference
<XKeysSupplier
> xKeySup(m_xTable
,UNO_QUERY
);
1056 Reference
<XIndexAccess
> xKeys
;
1058 xKeys
= xKeySup
->getKeys();
1060 Reference
<XColumnsSupplier
> xKeyColsSup
;
1061 Reference
<XNameAccess
> xKeyColumns
;
1064 Reference
<XPropertySet
> xProp
;
1065 sal_Int32 nCount
= xKeys
->getCount();
1066 for(sal_Int32 i
=0;i
< nCount
;++i
)
1068 xKeys
->getByIndex(i
) >>= xProp
;
1069 OSL_ENSURE(xProp
.is(),"Key is invalid: NULL!");
1072 sal_Int32 nKeyType
= 0;
1073 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
1074 if(KeyType::PRIMARY
== nKeyType
)
1076 xKeyColsSup
.set(xProp
,UNO_QUERY
);
1077 OSL_ENSURE(xKeyColsSup
.is(),"Columnsupplier is null!");
1078 xKeyColumns
= xKeyColsSup
->getColumns();
1087 // -----------------------------------------------------------------------------
1088 sal_Bool
OTableController::checkColumns(sal_Bool _bNew
) throw(::com::sun::star::sdbc::SQLException
)
1090 sal_Bool bOk
= sal_True
;
1091 sal_Bool bFoundPKey
= sal_False
;
1092 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1094 ::comphelper::UStringMixEqual
bCase(xMetaData
.is() ? xMetaData
->supportsMixedCaseQuotedIdentifiers() : sal_True
);
1095 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1096 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1097 for(;aIter
!= aEnd
;++aIter
)
1099 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
1100 if (pFieldDesc
&& pFieldDesc
->GetName().getLength())
1102 bFoundPKey
|= (*aIter
)->IsPrimaryKey();
1103 // first check for duplicate names
1104 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter2
= aIter
+1;
1105 for(;aIter2
!= aEnd
;++aIter2
)
1107 OFieldDescription
* pCompareDesc
= (*aIter2
)->GetActFieldDescr();
1108 if (pCompareDesc
&& bCase(pCompareDesc
->GetName(),pFieldDesc
->GetName()))
1110 String strMessage
= String(ModuleRes(STR_TABLEDESIGN_DUPLICATE_NAME
));
1111 strMessage
.SearchAndReplaceAscii("$column$", pFieldDesc
->GetName());
1112 OSQLWarningBox( getView(), strMessage
).Execute();
1120 if(_bNew
&& xMetaData
.is() && xMetaData
->supportsCoreSQLGrammar())
1122 String
sTitle(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY_HEAD
));
1123 String
sMsg(ModuleRes(STR_TABLEDESIGN_NO_PRIM_KEY
));
1124 OSQLMessageBox
aBox(getView(), sTitle
,sMsg
, WB_YES_NO_CANCEL
| WB_DEF_YES
);
1126 INT16 nReturn
= aBox
.Execute();
1128 if (nReturn
== RET_YES
)
1130 ::boost::shared_ptr
<OTableRow
> pNewRow(new OTableRow());
1131 TOTypeInfoSP pTypeInfo
= ::dbaui::queryPrimaryKeyType(m_aTypeInfo
);
1133 if ( pTypeInfo
.get() )
1135 pNewRow
->SetFieldType( pTypeInfo
);
1136 OFieldDescription
* pActFieldDescr
= pNewRow
->GetActFieldDescr();
1138 pActFieldDescr
->SetAutoIncrement(sal_False
); // #95927# pTypeInfo->bAutoIncrement
1139 pActFieldDescr
->SetIsNullable(ColumnValue::NO_NULLS
);
1141 pActFieldDescr
->SetName( createUniqueName(::rtl::OUString::createFromAscii("ID") ));
1142 pActFieldDescr
->SetPrimaryKey( sal_True
);
1143 m_vRowList
.insert(m_vRowList
.begin(),pNewRow
);
1145 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->Invalidate();
1146 static_cast<OTableDesignView
*>(getView())->GetEditorCtrl()->RowInserted(0);
1147 } // if ( pTypeInfo.get() )
1149 else if (nReturn
== RET_CANCEL
)
1155 // -----------------------------------------------------------------------------
1156 void OTableController::alterColumns()
1158 Reference
<XColumnsSupplier
> xColSup(m_xTable
,UNO_QUERY_THROW
);
1159 OSL_ENSURE(xColSup
.is(),"What happen here?!");
1161 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
1162 Reference
<XIndexAccess
> xIdxColumns(xColumns
,UNO_QUERY_THROW
);
1163 OSL_ENSURE(xColumns
.is(),"No columns");
1164 if ( !xColumns
.is() )
1166 Reference
<XAlterTable
> xAlter(m_xTable
,UNO_QUERY
); // can be null
1168 sal_Int32 nColumnCount
= xIdxColumns
->getCount();
1169 Reference
<XDrop
> xDrop(xColumns
,UNO_QUERY
); // can be null
1170 Reference
<XAppend
> xAppend(xColumns
,UNO_QUERY
); // can be null
1171 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
); // can be null
1173 sal_Bool bReload
= sal_False
; // refresh the data
1175 // contains all columns names which are already handled those which are not in the list will be deleted
1176 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1178 ::std::map
< ::rtl::OUString
,sal_Bool
,::comphelper::UStringMixLess
> aColumns(xMetaData
.is() ? (xMetaData
->supportsMixedCaseQuotedIdentifiers() ? true : false): sal_True
);
1179 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1180 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1181 // first look for columns where something other than the name changed
1183 for(;aIter
!= aEnd
;++aIter
,++nPos
)
1185 OSL_ENSURE(*aIter
,"OTableRow is null!");
1186 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1189 if ( (*aIter
)->IsReadOnly() )
1191 aColumns
[pField
->GetName()] = sal_True
;
1195 Reference
<XPropertySet
> xColumn
;
1196 if ( xColumns
->hasByName(pField
->GetName()) )
1198 aColumns
[pField
->GetName()] = sal_True
;
1199 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1200 OSL_ENSURE(xColumn
.is(),"Column is null!");
1202 sal_Int32 nType
=0,nPrecision
=0,nScale
=0,nNullable
=0;
1203 sal_Bool bAutoIncrement
= false;
1204 ::rtl::OUString sTypeName
;
1206 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1207 xColumn
->getPropertyValue(PROPERTY_PRECISION
) >>= nPrecision
;
1208 xColumn
->getPropertyValue(PROPERTY_SCALE
) >>= nScale
;
1209 xColumn
->getPropertyValue(PROPERTY_ISNULLABLE
) >>= nNullable
;
1210 xColumn
->getPropertyValue(PROPERTY_ISAUTOINCREMENT
) >>= bAutoIncrement
;
1212 try { xColumn
->getPropertyValue(PROPERTY_TYPENAME
) >>= sTypeName
; }
1213 catch( const Exception
& )
1215 OSL_ENSURE( sal_False
, "no TypeName property?!" );
1216 // since this is a last minute fix for #i41785#, I want to be on the safe side,
1217 // and catch errors here as early as possible (instead of the whole process of altering
1218 // the columns failing)
1219 // Normally, sdbcx::Column objects are expected to have a TypeName property
1222 // xColumn->getPropertyValue(PROPERTY_ISCURRENCY,::cppu::bool2any(pField->IsCurrency()));
1223 // check if something changed
1224 if((nType
!= pField
->GetType() ||
1225 sTypeName
!= pField
->GetTypeName() ||
1226 (nPrecision
!= pField
->GetPrecision() && nPrecision
) ||
1227 nScale
!= pField
->GetScale() ||
1228 nNullable
!= pField
->GetIsNullable() ||
1229 bAutoIncrement
!= pField
->IsAutoIncrement())&&
1230 xColumnFactory
.is())
1232 Reference
<XPropertySet
> xNewColumn
;
1233 xNewColumn
= xColumnFactory
->createDataDescriptor();
1234 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1235 // first try to alter the column
1236 sal_Bool bNotOk
= sal_False
;
1239 // first try if we can alter the column
1241 xAlter
->alterColumnByName(pField
->GetName(),xNewColumn
);
1243 catch(const SQLException
&)
1245 if(xDrop
.is() && xAppend
.is())
1247 String
aMessage( ModuleRes( STR_TABLEDESIGN_ALTER_ERROR
) );
1248 aMessage
.SearchAndReplaceAscii( "$column$", pField
->GetName() );
1250 SQLExceptionInfo
aError( ::cppu::getCaughtException() );
1251 OSQLWarningBox
aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
, &aError
);
1252 bNotOk
= aMsg
.Execute() == RET_YES
;
1257 // if something went wrong or we can't alter columns
1258 // drop and append a new one
1259 if((!xAlter
.is() || bNotOk
) && xDrop
.is() && xAppend
.is())
1261 xDrop
->dropByName(pField
->GetName());
1264 xAppend
->appendByDescriptor(xNewColumn
);
1266 catch(const SQLException
&)
1267 { // an error occured so we try to reactivate the old one
1268 xAppend
->appendByDescriptor(xColumn
);
1272 // exceptions are caught outside
1274 if(xColumns
->hasByName(pField
->GetName()))
1275 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1281 else if(xColumnFactory
.is() && xAlter
.is() && nPos
< nColumnCount
)
1282 { // we can't find the column so we could try it with the index before we drop and append a new column
1285 Reference
<XPropertySet
> xNewColumn
;
1286 xNewColumn
= xColumnFactory
->createDataDescriptor();
1287 ::dbaui::setColumnProperties(xNewColumn
,pField
);
1288 xAlter
->alterColumnByIndex(nPos
,xNewColumn
);
1289 if(xColumns
->hasByName(pField
->GetName()))
1290 { // ask for the append by name
1291 aColumns
[pField
->GetName()] = sal_True
;
1292 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1294 pField
->copyColumnSettingsTo(xColumn
);
1298 OSL_ENSURE(sal_False
, "OTableController::alterColumns: invalid column (2)!");
1301 catch(const SQLException
&)
1302 { // we couldn't alter the column so we have to add new columns
1304 if(xDrop
.is() && xAppend
.is())
1306 String
aMessage(ModuleRes(STR_TABLEDESIGN_ALTER_ERROR
));
1307 aMessage
.SearchAndReplaceAscii("$column$",pField
->GetName());
1308 OSQLWarningBox
aMsg( getView(), aMessage
, WB_YES_NO
| WB_DEF_YES
);
1309 if ( aMsg
.Execute() != RET_YES
)
1311 Reference
<XPropertySet
> xNewColumn(xIdxColumns
->getByIndex(nPos
),UNO_QUERY_THROW
);
1312 ::rtl::OUString sName
;
1313 xNewColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
1314 aColumns
[sName
] = sal_True
;
1315 aColumns
[pField
->GetName()] = sal_True
;
1325 } // for(sal_Int32 nPos = 0;aIter != aEnd;++aIter,++nPos)
1326 // alter column settings
1327 aIter
= m_vRowList
.begin();
1329 // first look for columns where something other than the name changed
1330 for(nPos
= 0;aIter
!= aEnd
;++aIter
,++nPos
)
1332 OSL_ENSURE(*aIter
,"OTableRow is null!");
1333 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1336 if ( (*aIter
)->IsReadOnly() )
1338 aColumns
[pField
->GetName()] = sal_True
;
1342 Reference
<XPropertySet
> xColumn
;
1343 if ( xColumns
->hasByName(pField
->GetName()) )
1345 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1346 Reference
<XPropertySetInfo
> xInfo
= xColumn
->getPropertySetInfo();
1347 if ( xInfo
->hasPropertyByName(PROPERTY_HELPTEXT
) )
1348 xColumn
->setPropertyValue(PROPERTY_HELPTEXT
,makeAny(pField
->GetDescription()));
1349 if(xInfo
->hasPropertyByName(PROPERTY_CONTROLDEFAULT
))
1350 xColumn
->setPropertyValue(PROPERTY_CONTROLDEFAULT
,pField
->GetControlDefault());
1351 if(xInfo
->hasPropertyByName(PROPERTY_FORMATKEY
))
1352 xColumn
->setPropertyValue(PROPERTY_FORMATKEY
,makeAny(pField
->GetFormatKey()));
1353 if(xInfo
->hasPropertyByName(PROPERTY_ALIGN
))
1354 xColumn
->setPropertyValue(PROPERTY_ALIGN
,makeAny(dbaui::mapTextAllign(pField
->GetHorJustify())));
1355 } // if ( xColumns->hasByName(pField->GetName()) )
1357 // second drop all columns which could be found by name
1358 Reference
<XNameAccess
> xKeyColumns
= getKeyColumns();
1359 // now we have to look for the columns who could be deleted
1362 Sequence
< ::rtl::OUString
> aColumnNames
= xColumns
->getElementNames();
1363 const ::rtl::OUString
* pIter
= aColumnNames
.getConstArray();
1364 const ::rtl::OUString
* pEnd
= pIter
+ aColumnNames
.getLength();
1365 for(;pIter
!= pEnd
;++pIter
)
1367 if(aColumns
.find(*pIter
) == aColumns
.end()) // found a column to delete
1369 if(xKeyColumns
.is() && xKeyColumns
->hasByName(*pIter
)) // check if this column is a member of the primary key
1371 String
aMsgT(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN
));
1372 aMsgT
.SearchAndReplaceAscii("$column$",*pIter
);
1373 String
aTitle(ModuleRes(STR_TBL_COLUMN_IS_KEYCOLUMN_TITLE
));
1374 OSQLMessageBox
aMsg(getView(),aTitle
,aMsgT
,WB_YES_NO
| WB_DEF_YES
);
1375 if(aMsg
.Execute() == RET_YES
)
1388 xDrop
->dropByName(*pIter
);
1390 catch (const SQLException
&)
1392 String
sError( ModuleRes( STR_TABLEDESIGN_COULD_NOT_DROP_COL
) );
1393 sError
.SearchAndReplaceAscii( "$column$", *pIter
);
1395 SQLException aNewException
;
1396 aNewException
.Message
= sError
;
1397 aNewException
.SQLState
= ::rtl::OUString::createFromAscii( "S1000" );
1398 aNewException
.NextException
= ::cppu::getCaughtException();
1400 throw aNewException
;
1406 // third append the new columns
1407 aIter
= m_vRowList
.begin();
1408 for(;aIter
!= aEnd
;++aIter
)
1410 OSL_ENSURE(*aIter
,"OTableRow is null!");
1411 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1412 if ( !pField
|| (*aIter
)->IsReadOnly() || aColumns
.find(pField
->GetName()) != aColumns
.end() )
1415 Reference
<XPropertySet
> xColumn
;
1416 if(!xColumns
->hasByName(pField
->GetName()))
1418 if(xColumnFactory
.is() && xAppend
.is())
1419 {// column not found by its name so we assume it is new
1421 xColumn
= xColumnFactory
->createDataDescriptor();
1422 ::dbaui::setColumnProperties(xColumn
,pField
);
1423 xAppend
->appendByDescriptor(xColumn
);
1424 if(xColumns
->hasByName(pField
->GetName()))
1425 { // ask for the append by name
1426 aColumns
[pField
->GetName()] = sal_True
;
1427 xColumns
->getByName(pField
->GetName()) >>= xColumn
;
1429 pField
->copyColumnSettingsTo(xColumn
);
1433 OSL_ENSURE(sal_False
, "OTableController::alterColumns: invalid column!");
1440 // check if we have to do something with the primary key
1441 sal_Bool bNeedDropKey
= sal_False
;
1442 sal_Bool bNeedAppendKey
= sal_False
;
1443 if ( xKeyColumns
.is() )
1445 aIter
= m_vRowList
.begin();
1446 for(;aIter
!= aEnd
;++aIter
)
1448 OSL_ENSURE(*aIter
,"OTableRow is null!");
1449 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1453 if ( pField
->IsPrimaryKey()
1454 && !xKeyColumns
->hasByName( pField
->GetName() )
1456 { // new primary key column inserted which isn't already in the columns selection
1457 bNeedDropKey
= bNeedAppendKey
= sal_True
;
1460 else if ( !pField
->IsPrimaryKey()
1461 && xKeyColumns
->hasByName( pField
->GetName() )
1463 { // found a column which currently is in the primary key, but is marked not to be anymore
1464 bNeedDropKey
= bNeedAppendKey
= sal_True
;
1470 { // no primary key available so we check if we should create one
1471 bNeedAppendKey
= sal_True
;
1477 if ( bNeedAppendKey
)
1479 Reference
< XKeysSupplier
> xKeySup( m_xTable
, UNO_QUERY
);
1480 appendPrimaryKey( xKeySup
,sal_False
);
1488 // -----------------------------------------------------------------------------
1489 void OTableController::dropPrimaryKey()
1491 SQLExceptionInfo aInfo
;
1494 Reference
<XKeysSupplier
> xKeySup(m_xTable
,UNO_QUERY
);
1495 Reference
<XIndexAccess
> xKeys
;
1497 xKeys
= xKeySup
->getKeys();
1501 Reference
<XPropertySet
> xProp
;
1502 for(sal_Int32 i
=0;i
< xKeys
->getCount();++i
)
1504 xProp
.set(xKeys
->getByIndex(i
),UNO_QUERY
);
1505 sal_Int32 nKeyType
= 0;
1506 xProp
->getPropertyValue(PROPERTY_TYPE
) >>= nKeyType
;
1507 if(KeyType::PRIMARY
== nKeyType
)
1509 Reference
<XDrop
> xDrop(xKeys
,UNO_QUERY
);
1510 xDrop
->dropByIndex(i
); // delete the key
1516 catch(const SQLContext
& e
)
1518 aInfo
= SQLExceptionInfo(e
);
1520 catch(const SQLWarning
& e
)
1522 aInfo
= SQLExceptionInfo(e
);
1524 catch(const SQLException
& e
)
1526 aInfo
= SQLExceptionInfo(e
);
1528 catch( const Exception
& )
1530 DBG_UNHANDLED_EXCEPTION();
1535 // -----------------------------------------------------------------------------
1536 void OTableController::assignTable()
1538 ::rtl::OUString sComposedName
;
1540 if(m_sName
.getLength())
1542 Reference
<XNameAccess
> xNameAccess
;
1543 Reference
<XTablesSupplier
> xSup(getConnection(),UNO_QUERY
);
1546 xNameAccess
= xSup
->getTables();
1547 OSL_ENSURE(xNameAccess
.is(),"no nameaccess for the queries!");
1549 Reference
<XPropertySet
> xProp
;
1550 if(xNameAccess
->hasByName(m_sName
) && ::cppu::extractInterface(xProp
,xNameAccess
->getByName(m_sName
)) && xProp
.is())
1553 startTableListening();
1555 // check if we set the table editable
1556 Reference
<XDatabaseMetaData
> xMeta
= getConnection()->getMetaData();
1557 setEditable( xMeta
.is() && !xMeta
->isReadOnly() && (isAlterAllowed() || isDropAllowed() || isAddAllowed()) );
1560 ::std::for_each(m_vRowList
.begin(),m_vRowList
.end(),boost::bind( &OTableRow::SetReadOnly
, _1
, boost::cref( sal_True
)));
1563 // be notified when the table is in disposing
1570 // -----------------------------------------------------------------------------
1571 sal_Bool
OTableController::isAddAllowed() const
1573 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1574 sal_Bool bAddAllowed
= !m_xTable
.is();
1576 bAddAllowed
= Reference
<XAppend
>(xColsSup
->getColumns(),UNO_QUERY
).is();
1580 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1581 bAddAllowed
= bAddAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithAddColumn());
1585 DBG_UNHANDLED_EXCEPTION();
1586 bAddAllowed
= sal_False
;
1591 // -----------------------------------------------------------------------------
1592 sal_Bool
OTableController::isDropAllowed() const
1594 Reference
<XColumnsSupplier
> xColsSup(m_xTable
,UNO_QUERY
);
1595 sal_Bool bDropAllowed
= !m_xTable
.is();
1598 Reference
<XNameAccess
> xNameAccess
= xColsSup
->getColumns();
1599 bDropAllowed
= Reference
<XDrop
>(xNameAccess
,UNO_QUERY
).is() && xNameAccess
->hasElements();
1602 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1603 bDropAllowed
= bDropAllowed
|| ( xMetaData
.is() && xMetaData
->supportsAlterTableWithDropColumn());
1605 return bDropAllowed
;
1607 // -----------------------------------------------------------------------------
1608 sal_Bool
OTableController::isAlterAllowed() const
1610 sal_Bool
bAllowed(!m_xTable
.is() || Reference
<XAlterTable
>(m_xTable
,UNO_QUERY
).is());
1613 // -----------------------------------------------------------------------------
1614 void OTableController::reSyncRows()
1616 sal_Bool bAlterAllowed
= isAlterAllowed();
1617 sal_Bool bAddAllowed
= isAddAllowed();
1618 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aIter
= m_vRowList
.begin();
1619 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::iterator aEnd
= m_vRowList
.end();
1620 for(;aIter
!= aEnd
;++aIter
)
1622 OSL_ENSURE(*aIter
,"OTableRow is null!");
1623 OFieldDescription
* pField
= (*aIter
)->GetActFieldDescr();
1625 (*aIter
)->SetReadOnly(!bAlterAllowed
);
1627 (*aIter
)->SetReadOnly(!bAddAllowed
);
1630 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our informations
1632 getUndoMgr()->Clear(); // clear all undo redo things
1633 setModified(sal_False
); // and we are not modified yet
1635 // -----------------------------------------------------------------------------
1636 ::rtl::OUString
OTableController::createUniqueName(const ::rtl::OUString
& _rName
)
1638 ::rtl::OUString sName
= _rName
;
1639 Reference
< XDatabaseMetaData
> xMetaData
= getMetaData( );
1641 ::comphelper::UStringMixEqual
bCase(xMetaData
.is() ? xMetaData
->supportsMixedCaseQuotedIdentifiers() : sal_True
);
1643 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1644 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1645 for(sal_Int32 i
=0;aIter
!= aEnd
;++aIter
)
1647 OFieldDescription
* pFieldDesc
= (*aIter
)->GetActFieldDescr();
1648 if (pFieldDesc
&& pFieldDesc
->GetName().getLength() && bCase(sName
,pFieldDesc
->GetName()))
1649 { // found a second name of _rName so we need another
1650 sName
= _rName
+ ::rtl::OUString::valueOf(++i
);
1651 aIter
= m_vRowList
.begin(); // and retry
1656 // -----------------------------------------------------------------------------
1657 ::rtl::OUString
OTableController::getPrivateTitle() const
1659 ::rtl::OUString sTitle
;
1663 if ( m_sName
.getLength() && getConnection().is() )
1665 if ( m_xTable
.is() )
1666 sTitle
= ::dbtools::composeTableName( getConnection()->getMetaData(), m_xTable
, ::dbtools::eInDataManipulation
, false, false, false );
1670 if ( !sTitle
.getLength() )
1672 String aName
= String(ModuleRes(STR_TBL_TITLE
));
1673 sTitle
= aName
.GetToken(0,' ');
1674 sTitle
+= ::rtl::OUString::valueOf(getCurrentStartNumber());
1677 catch( const Exception
& )
1679 DBG_UNHANDLED_EXCEPTION();
1683 // -----------------------------------------------------------------------------
1684 void OTableController::reload()
1686 loadData(); // fill the column information form the table
1687 static_cast<OTableDesignView
*>(getView())->reSync(); // show the windows and fill with our informations
1688 getUndoMgr()->Clear(); // clear all undo redo things
1689 setModified(sal_False
); // and we are not modified yet
1690 static_cast<OTableDesignView
*>(getView())->Invalidate();
1692 // -----------------------------------------------------------------------------
1693 sal_Int32
OTableController::getFirstEmptyRowPosition() const
1695 sal_Int32 nRet
= -1;
1696 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aIter
= m_vRowList
.begin();
1697 ::std::vector
< ::boost::shared_ptr
<OTableRow
> >::const_iterator aEnd
= m_vRowList
.end();
1698 for(;aIter
!= aEnd
;++aIter
)
1700 if ( !*aIter
|| !(*aIter
)->GetActFieldDescr() || !(*aIter
)->GetActFieldDescr()->GetName().getLength() )
1702 nRet
= aIter
- m_vRowList
.begin();
1708 // -----------------------------------------------------------------------------
1709 bool OTableController::isAutoIncrementPrimaryKey() const
1711 return getSdbMetaData().isAutoIncrementPrimaryKey();
1713 // -----------------------------------------------------------------------------