1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <cstdarg> 28 29 #include <svtools/svmedit.hxx> 30 #include <svl/eitem.hxx> 31 #include <svl/whiter.hxx> 32 #include <sfx2/event.hxx> 33 #include <sfx2/dispatch.hxx> 34 #include <sfx2/viewfrm.hxx> 35 #ifndef _MSGBOX_HXX //autogen 36 #include <vcl/msgbox.hxx> 37 #endif 38 #include <svl/stritem.hxx> 39 #include <svl/itemset.hxx> 40 #include <sfx2/request.hxx> 41 #include <com/sun/star/sdb/CommandType.hpp> 42 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 43 #include <com/sun/star/container/XNameAccess.hpp> 44 #include <com/sun/star/sdbc/XDataSource.hpp> 45 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 46 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 47 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 48 #include <com/sun/star/sdb/XDatabaseAccess.hpp> 49 #include <com/sun/star/beans/XPropertySet.hpp> 50 #include <com/sun/star/container/XChild.hpp> 51 #include <comphelper/processfactory.hxx> 52 #include <com/sun/star/sdbc/XRowSet.hpp> 53 #include <sfx2/frame.hxx> 54 #include <fldmgr.hxx> 55 #include <fldbas.hxx> 56 #include "dbmgr.hxx" 57 #include <comphelper/uno3.hxx> 58 #include <svx/dataaccessdescriptor.hxx> 59 #include <memory> 60 61 #include <vcl/svapp.hxx> 62 63 #include "view.hxx" 64 #include "wrtsh.hxx" 65 #include "swtypes.hxx" 66 #include "cmdid.h" 67 #include "swevent.hxx" 68 #include "shells.hrc" 69 #include "textsh.hxx" 70 #include "swabstdlg.hxx" 71 #include "dbui.hrc" 72 73 #include <unomid.h> 74 75 using namespace ::svx; 76 using namespace ::com::sun::star; 77 using namespace ::com::sun::star::uno; 78 using namespace ::com::sun::star::container; 79 using namespace ::com::sun::star::lang; 80 using namespace ::com::sun::star::sdb; 81 using namespace ::com::sun::star::sdbc; 82 using namespace ::com::sun::star::sdbcx; 83 using namespace ::com::sun::star::beans; 84 85 86 #define DB_DD_DELIM 0x0b 87 88 struct DBTextStruct_Impl 89 { 90 SwDBData aDBData; 91 Sequence<Any> aSelection; 92 Reference<XResultSet> xCursor; 93 Reference<XConnection> xConnection; 94 }; 95 inline void AddSelList( List& rLst, long nRow ) 96 { 97 rLst.Insert( (void*)nRow , LIST_APPEND ); 98 } 99 void SwTextShell::ExecDB(SfxRequest &rReq) 100 { 101 const SfxItemSet *pArgs = rReq.GetArgs(); 102 SwNewDBMgr* pNewDBMgr = GetShell().GetNewDBMgr(); 103 sal_uInt16 nSlot = rReq.GetSlot(); 104 ::rtl::OUString sSourceArg, sCommandArg; 105 sal_Int32 nCommandTypeArg = 0; 106 107 const SfxPoolItem* pSourceItem = 0; 108 const SfxPoolItem* pCursorItem = 0; 109 const SfxPoolItem* pConnectionItem = 0; 110 const SfxPoolItem* pCommandItem = 0; 111 const SfxPoolItem* pCommandTypeItem = 0; 112 const SfxPoolItem* pSelectionItem = 0; 113 114 // first get the selection of rows to be inserted 115 pArgs->GetItemState(FN_DB_DATA_SELECTION_ANY, sal_False, &pSelectionItem); 116 117 Sequence<Any> aSelection; 118 if(pSelectionItem) 119 ((SfxUsrAnyItem*)pSelectionItem)->GetValue() >>= aSelection; 120 121 // get the data source name 122 pArgs->GetItemState(FN_DB_DATA_SOURCE_ANY, sal_False, &pSourceItem); 123 if(pSourceItem) 124 ((const SfxUsrAnyItem*)pSourceItem)->GetValue() >>= sSourceArg; 125 126 // get the command 127 pArgs->GetItemState(FN_DB_DATA_COMMAND_ANY, sal_False, &pCommandItem); 128 if(pCommandItem) 129 ((const SfxUsrAnyItem*)pCommandItem)->GetValue() >>= sCommandArg; 130 131 // get the command type 132 pArgs->GetItemState(FN_DB_DATA_COMMAND_TYPE_ANY, sal_False, &pCommandTypeItem); 133 if(pCommandTypeItem) 134 ((const SfxUsrAnyItem*)pCommandTypeItem)->GetValue() >>= nCommandTypeArg; 135 136 Reference<XConnection> xConnection; 137 pArgs->GetItemState(FN_DB_CONNECTION_ANY, sal_False, &pConnectionItem); 138 if ( pConnectionItem ) 139 ((const SfxUsrAnyItem*)pConnectionItem)->GetValue() >>= xConnection; 140 // may be we even get no connection 141 if ( !xConnection.is() ) 142 { 143 Reference<XDataSource> xSource; 144 xConnection = pNewDBMgr->GetConnection(sSourceArg, xSource); 145 } 146 if(!xConnection.is()) 147 return ; 148 149 // get the cursor, we use to travel, may be NULL 150 Reference<XResultSet> xCursor; 151 pArgs->GetItemState(FN_DB_DATA_CURSOR_ANY, sal_False, &pCursorItem); 152 if ( pCursorItem ) 153 ((const SfxUsrAnyItem*)pCursorItem)->GetValue() >>= xCursor; 154 155 switch (nSlot) 156 { 157 case FN_QRY_INSERT: 158 { 159 if(pSourceItem && pCommandItem && pCommandTypeItem) 160 { 161 DBTextStruct_Impl* pNew = new DBTextStruct_Impl; 162 pNew->aDBData.sDataSource = sSourceArg; 163 pNew->aDBData.sCommand = sCommandArg; 164 pNew->aDBData.nCommandType = nCommandTypeArg; 165 pNew->aSelection = aSelection; 166 //if the cursor is NULL, it must be created inside InsertDBTextHdl 167 // because it called via a PostUserEvent 168 pNew->xCursor = xCursor; 169 pNew->xConnection = xConnection; 170 171 Application::PostUserEvent( STATIC_LINK( this, SwBaseShell, 172 InsertDBTextHdl ), pNew ); 173 // the pNew will be removed in InsertDBTextHdl !! 174 } 175 } 176 break; 177 178 case FN_QRY_MERGE_FIELD: 179 { 180 // we don't get any cursor, so we must create our own 181 sal_Bool bDisposeResultSet = sal_False; 182 if ( !xCursor.is() ) 183 { 184 xCursor = SwNewDBMgr::createCursor(sSourceArg,sCommandArg,nCommandTypeArg,xConnection); 185 bDisposeResultSet = xCursor.is(); 186 } 187 188 ODataAccessDescriptor aDescriptor; 189 aDescriptor.setDataSource(sSourceArg); 190 aDescriptor[daCommand] <<= sCommandArg; 191 aDescriptor[daCursor] <<= xCursor; 192 aDescriptor[daSelection] <<= aSelection; 193 aDescriptor[daCommandType] <<= nCommandTypeArg; 194 195 SwMergeDescriptor aMergeDesc( DBMGR_MERGE, *GetShellPtr(), aDescriptor ); 196 pNewDBMgr->MergeNew(aMergeDesc); 197 198 if ( bDisposeResultSet ) 199 ::comphelper::disposeComponent(xCursor); 200 } 201 break; 202 203 case FN_QRY_INSERT_FIELD: 204 { 205 const SfxPoolItem* pColumnItem = 0; 206 const SfxPoolItem* pColumnNameItem = 0; 207 208 pArgs->GetItemState(FN_DB_COLUMN_ANY, sal_False, &pColumnItem); 209 pArgs->GetItemState(FN_DB_DATA_COLUMN_NAME_ANY, sal_False, &pColumnNameItem); 210 211 ::rtl::OUString sColumnName; 212 if(pColumnNameItem) 213 ((SfxUsrAnyItem*)pColumnNameItem)->GetValue() >>= sColumnName; 214 String sDBName = sSourceArg; 215 sDBName += DB_DELIM; 216 sDBName += (String)sCommandArg; 217 sDBName += DB_DELIM; 218 sDBName += String::CreateFromInt32(nCommandTypeArg); 219 sDBName += DB_DELIM; 220 sDBName += (String)sColumnName; 221 222 SwFldMgr aFldMgr(GetShellPtr()); 223 SwInsertFld_Data aData(TYP_DBFLD, 0, sDBName, aEmptyStr, 0, sal_False, sal_True); 224 if(pConnectionItem) 225 aData.aDBConnection = ((SfxUsrAnyItem*)pConnectionItem)->GetValue(); 226 if(pColumnItem) 227 aData.aDBColumn = ((SfxUsrAnyItem*)pColumnItem)->GetValue(); 228 aFldMgr.InsertFld(aData); 229 SfxViewFrame* pViewFrame = GetView().GetViewFrame(); 230 uno::Reference< frame::XDispatchRecorder > xRecorder = 231 pViewFrame->GetBindings().GetRecorder(); 232 if ( xRecorder.is() ) 233 { 234 SfxRequest aReq( pViewFrame, FN_INSERT_DBFIELD ); 235 aReq.AppendItem( SfxUInt16Item(FN_PARAM_FIELD_TYPE, TYP_DBFLD)); 236 aReq.AppendItem( SfxStringItem( FN_INSERT_DBFIELD, sDBName )); 237 aReq.AppendItem( SfxStringItem( FN_PARAM_1, sCommandArg )); 238 aReq.AppendItem( SfxStringItem( FN_PARAM_2, sColumnName )); 239 aReq.AppendItem( SfxInt32Item( FN_PARAM_3, nCommandTypeArg)); 240 aReq.Done(); 241 } 242 } 243 break; 244 245 default: 246 ASSERT(!this, falscher Dispatcher); 247 return; 248 } 249 } 250 251 /*-------------------------------------------------------------------- 252 Beschreibung: 253 --------------------------------------------------------------------*/ 254 255 IMPL_STATIC_LINK( SwBaseShell, InsertDBTextHdl, DBTextStruct_Impl*, pDBStruct ) 256 { 257 if( pDBStruct ) 258 { 259 sal_Bool bDispose = sal_False; 260 Reference< sdbc::XConnection> xConnection = pDBStruct->xConnection; 261 Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,pDBStruct->aDBData.sDataSource); 262 // #111987# the connection is disposed an so no parent has been found 263 if(xConnection.is() && !xSource.is()) 264 return 0; 265 266 if ( !xConnection.is() ) 267 { 268 xConnection = SwNewDBMgr::GetConnection(pDBStruct->aDBData.sDataSource, xSource); 269 bDispose = sal_True; 270 } 271 272 Reference< XColumnsSupplier> xColSupp; 273 if(xConnection.is()) 274 xColSupp = SwNewDBMgr::GetColumnSupplier(xConnection, 275 pDBStruct->aDBData.sCommand, 276 pDBStruct->aDBData.nCommandType == CommandType::QUERY ? 277 SW_DB_SELECT_QUERY : SW_DB_SELECT_TABLE); 278 279 if( xColSupp.is() ) 280 { 281 SwDBData aDBData = pDBStruct->aDBData; 282 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); 283 DBG_ASSERT(pFact, "SwAbstractDialogFactory fail!"); 284 ::std::auto_ptr<AbstractSwInsertDBColAutoPilot>pDlg (pFact->CreateSwInsertDBColAutoPilot( pThis->GetView(), 285 xSource, 286 xColSupp, 287 aDBData, 288 DLG_AP_INSERT_DB_SEL )); 289 if( RET_OK == pDlg->Execute() ) 290 { 291 Reference <XResultSet> xResSet = pDBStruct->xCursor; 292 pDlg->DataToDoc( pDBStruct->aSelection, xSource, xConnection, xResSet); 293 } 294 } 295 if ( bDispose ) 296 ::comphelper::disposeComponent(xConnection); 297 } 298 299 delete pDBStruct; 300 return 0; 301 } 302 303 304 305