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 };
AddSelList(List & rLst,long nRow)95 inline void AddSelList( List& rLst, long nRow )
96 {
97 rLst.Insert( (void*)nRow , LIST_APPEND );
98 }
ExecDB(SfxRequest & rReq)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, NULL, 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
IMPL_STATIC_LINK(SwBaseShell,InsertDBTextHdl,DBTextStruct_Impl *,pDBStruct)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