Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include "MColumnAlias.hxx"
22 : #include "MQueryHelper.hxx"
23 : #include "MConnection.hxx"
24 :
25 : #include "MorkParser.hxx"
26 : #include <stdlib.h>
27 : #include <sstream>
28 : #include <string>
29 : #include <vector>
30 : #include <algorithm>
31 : #include <string.h>
32 :
33 : #include "resource/mork_res.hrc"
34 : #include "resource/common_res.hrc"
35 :
36 : #include <connectivity/dbexception.hxx>
37 : #include <unotools/textsearch.hxx>
38 :
39 : using namespace connectivity::mork;
40 : using namespace connectivity;
41 : using namespace ::com::sun::star::beans;
42 : using namespace ::com::sun::star::sdbc;
43 :
44 :
45 : extern
46 : ::std::vector< sal_Bool > entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression* _aExpr, MQueryHelperResultEntry* entry);
47 :
48 30 : MQueryHelperResultEntry::MQueryHelperResultEntry()
49 : {
50 30 : }
51 :
52 30 : MQueryHelperResultEntry::~MQueryHelperResultEntry()
53 : {
54 30 : }
55 :
56 38 : OUString MQueryHelperResultEntry::getValue( const OString &key ) const
57 : {
58 38 : FieldMap::const_iterator iter = m_Fields.find( key );
59 38 : if ( iter == m_Fields.end() )
60 : {
61 0 : return OUString();
62 : }
63 : else
64 : {
65 38 : return iter->second;
66 : }
67 : }
68 :
69 390 : void MQueryHelperResultEntry::setValue( const OString &key, const OUString & rValue)
70 : {
71 390 : m_Fields[ key ] = rValue;
72 390 : }
73 :
74 4 : MQueryHelper::MQueryHelper(const OColumnAlias& _ca)
75 : :m_nIndex( 0 )
76 : ,m_bHasMore( true )
77 : ,m_bAtEnd( false )
78 : ,m_rColumnAlias( _ca )
79 4 : ,m_aError()
80 : {
81 4 : m_aResults.clear();
82 4 : }
83 :
84 8 : MQueryHelper::~MQueryHelper()
85 : {
86 4 : clear_results();
87 : OSL_TRACE("OUT MQueryHelper::~MQueryHelper()");
88 4 : }
89 :
90 :
91 4 : void MQueryHelper::setAddressbook(OUString &ab)
92 : {
93 4 : ::osl::MutexGuard aGuard(m_aMutex);
94 :
95 4 : m_aAddressbook = ab;
96 :
97 4 : OSL_TRACE("\tOUT MQuery::setAddressbook()");
98 4 : }
99 :
100 22 : void MQueryHelper::append(MQueryHelperResultEntry* resEnt)
101 : {
102 22 : if ( resEnt != NULL ) {
103 22 : m_aResults.push_back( resEnt );
104 22 : m_bAtEnd = false;
105 : }
106 22 : }
107 :
108 8 : void MQueryHelper::clear_results()
109 : {
110 8 : resultsArray::iterator iter = m_aResults.begin();
111 38 : while ( iter != m_aResults.end() ) {
112 22 : delete (*iter);
113 22 : ++iter;
114 : }
115 8 : m_aResults.clear();
116 8 : }
117 :
118 4 : void MQueryHelper::reset()
119 : {
120 4 : m_nIndex = 0;
121 4 : m_bHasMore = true;
122 4 : m_bAtEnd = false;
123 4 : clear_results();
124 4 : m_aError.reset();
125 4 : }
126 :
127 : MQueryHelperResultEntry*
128 28 : MQueryHelper::getByIndex(sal_uInt32 nRow)
129 : {
130 : // Row numbers are from 1 to N, need to ensure this, and then
131 : // substract 1
132 28 : if ( nRow < 1 ) {
133 0 : return( NULL );
134 : }
135 28 : return m_aResults[nRow -1];
136 : }
137 :
138 74 : sal_Int32 MQueryHelper::getResultCount() const
139 : {
140 74 : sal_Int32 result = static_cast<sal_Int32>(m_aResults.size());
141 :
142 74 : return result;
143 : }
144 :
145 :
146 :
147 0 : bool MQueryHelper::queryComplete() const
148 : {
149 0 : return true;
150 : }
151 :
152 0 : bool MQueryHelper::checkRowAvailable( sal_Int32 nDBRow )
153 : {
154 : /*
155 : while (!queryComplete() && getResultCount() <= (sal_uInt32)nDBRow)
156 : {
157 : if ( !m_aQueryHelper->waitForRow( nDBRow ) ) {
158 : m_aError = m_aQueryHelper->getError();
159 : return( sal_False );
160 : }
161 : }
162 : */
163 0 : return( getResultCount() > nDBRow );
164 : }
165 :
166 :
167 28 : bool MQueryHelper::getRowValue( ORowSetValue& rValue, sal_Int32 nDBRow,const OUString& aDBColumnName, sal_Int32 nType )
168 : {
169 28 : MQueryHelperResultEntry* xResEntry = getByIndex( nDBRow );
170 :
171 : OSL_ENSURE( xResEntry != NULL, "xResEntry == NULL");
172 28 : if (xResEntry == NULL )
173 : {
174 0 : rValue.setNull();
175 0 : return false;
176 : }
177 28 : switch ( nType )
178 : {
179 : case DataType::VARCHAR:
180 28 : rValue = xResEntry->getValue( m_rColumnAlias.getProgrammaticNameOrFallbackToUTF8Alias( aDBColumnName ) );
181 28 : break;
182 :
183 : default:
184 0 : rValue.setNull();
185 0 : break;
186 : }
187 :
188 28 : return true;
189 : }
190 :
191 4 : sal_Int32 MQueryHelper::executeQuery(OConnection* xConnection, MQueryExpression & expr)
192 : {
193 4 : reset();
194 :
195 4 : OString oStringTable = OUStringToOString( m_aAddressbook, RTL_TEXTENCODING_UTF8 );
196 8 : std::set<int> listRecords;
197 4 : bool handleListTable = false;
198 4 : MorkParser* xMork = xConnection->getMorkParser(oStringTable);
199 :
200 : // check if we are retrieving the default table
201 4 : if (oStringTable != "AddressBook" && oStringTable != "CollectedAddressBook")
202 : {
203 2 : handleListTable = true;
204 : // retrieve row ids for that list table
205 2 : std::string listTable = oStringTable.getStr();
206 2 : xMork->getRecordKeysForListTable(listTable, listRecords);
207 : }
208 4 : MorkTableMap::iterator tableIter;
209 4 : MorkTableMap *Tables = xMork->getTables( 0x80 );
210 4 : if (!Tables)
211 0 : return -1;
212 4 : MorkRowMap *Rows = 0;
213 4 : MorkRowMap::iterator rowIter;
214 :
215 : // Iterate all tables
216 8 : for ( tableIter = Tables->begin(); tableIter != Tables->end(); ++tableIter )
217 : {
218 4 : if (tableIter->first != 1) break;
219 4 : Rows = xMork->getRows( 0x80, &tableIter->second );
220 4 : if ( Rows )
221 : {
222 : // Iterate all rows
223 44 : for ( rowIter = Rows->begin(); rowIter != Rows->end(); ++rowIter )
224 : {
225 : // list specific table
226 : // only retrieve rowIds that belong to that list table.
227 40 : if (handleListTable)
228 : {
229 20 : int rowId = rowIter->first;
230 : // belongs this row id to the list table?
231 20 : if (listRecords.end() == std::find(listRecords.begin(), listRecords.end(), rowId))
232 : {
233 : // no, skip it
234 10 : continue;
235 : }
236 : }
237 :
238 30 : MQueryHelperResultEntry* entry = new MQueryHelperResultEntry();
239 1260 : for (MorkCells::iterator CellsIter = rowIter->second.begin();
240 840 : CellsIter != rowIter->second.end(); ++CellsIter )
241 : {
242 390 : std::string column = xMork->getColumn(CellsIter->first);
243 780 : std::string value = xMork->getValue(CellsIter->second);
244 780 : OString key(column.c_str(), static_cast<sal_Int32>(column.size()));
245 780 : OString valueOString(value.c_str(), static_cast<sal_Int32>(value.size()));
246 780 : OUString valueOUString = OStringToOUString( valueOString, RTL_TEXTENCODING_UTF8 );
247 390 : entry->setValue(key, valueOUString);
248 390 : }
249 30 : ::std::vector< sal_Bool > vector = entryMatchedByExpression(this, &expr, entry);
250 30 : bool result = true;
251 40 : for (::std::vector<sal_Bool>::iterator iter = vector.begin(); iter != vector.end(); ++iter)
252 : {
253 10 : result = result && *iter;
254 : }
255 30 : if (result)
256 : {
257 22 : append(entry);
258 : }
259 : else
260 : {
261 8 : delete entry;
262 : }
263 30 : }
264 : }
265 : }
266 8 : return 0;
267 : }
268 :
269 30 : ::std::vector< sal_Bool > entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression* _aExpr, MQueryHelperResultEntry* entry)
270 : {
271 30 : ::std::vector< sal_Bool > resultVector;
272 30 : MQueryExpression::ExprVector::const_iterator evIter;
273 120 : for( evIter = _aExpr->getExpressions().begin();
274 80 : evIter != _aExpr->getExpressions().end();
275 : ++evIter )
276 : {
277 10 : if ( (*evIter)->isStringExpr() ) {
278 10 : MQueryExpressionString* evStr = static_cast<MQueryExpressionString*> (*evIter);
279 : // Set the 'name' property of the boolString.
280 10 : OString attrName = _aQuery->getColumnAlias().getProgrammaticNameOrFallbackToUTF8Alias( evStr->getName() );
281 : SAL_INFO("connectivity.mork", "Name = " << attrName.getStr());
282 10 : bool requiresValue = true;
283 20 : OUString currentValue = entry->getValue(attrName);
284 10 : if (evStr->getCond() == MQueryOp::Exists || evStr->getCond() == MQueryOp::DoesNotExist)
285 : {
286 0 : requiresValue = false;
287 : }
288 10 : if (requiresValue)
289 : {
290 : SAL_INFO("connectivity.mork", "Value = " << evStr->getValue() );
291 10 : OUString searchedValue = evStr->getValue();
292 10 : if (evStr->getCond() == MQueryOp::Is) {
293 : SAL_INFO("connectivity.mork", "MQueryOp::Is; done");
294 0 : resultVector.push_back((currentValue == searchedValue) ? sal_True : sal_False);
295 10 : } else if (evStr->getCond() == MQueryOp::IsNot) {
296 : SAL_INFO("connectivity.mork", "MQueryOp::IsNot; done");
297 0 : resultVector.push_back((currentValue == searchedValue) ? sal_False : sal_True);
298 10 : } else if (evStr->getCond() == MQueryOp::EndsWith) {
299 : SAL_INFO("connectivity.mork", "MQueryOp::EndsWith; done");
300 10 : resultVector.push_back((currentValue.endsWith(searchedValue)) ? sal_True : sal_False);
301 0 : } else if (evStr->getCond() == MQueryOp::BeginsWith) {
302 : SAL_INFO("connectivity.mork", "MQueryOp::BeginsWith; done");
303 0 : resultVector.push_back((currentValue.startsWith(searchedValue)) ? sal_True : sal_False);
304 0 : } else if (evStr->getCond() == MQueryOp::Contains) {
305 : SAL_INFO("connectivity.mork", "MQueryOp::Contains; done");
306 0 : resultVector.push_back((currentValue.indexOf(searchedValue) == -1) ? sal_False : sal_True);
307 0 : } else if (evStr->getCond() == MQueryOp::DoesNotContain) {
308 : SAL_INFO("connectivity.mork", "MQueryOp::DoesNotContain; done");
309 0 : resultVector.push_back((currentValue.indexOf(searchedValue) == -1) ? sal_True : sal_False);
310 0 : } else if (evStr->getCond() == MQueryOp::RegExp) {
311 : SAL_INFO("connectivity.mork", "MQueryOp::RegExp; done");
312 : utl::SearchParam param(
313 0 : searchedValue, utl::SearchParam::SRCH_REGEXP);
314 0 : utl::TextSearch ts(param, LANGUAGE_DONTKNOW);
315 0 : sal_Int32 start = 0;
316 0 : sal_Int32 end = currentValue.getLength();
317 : resultVector.push_back(
318 0 : ts.SearchForward(currentValue, &start, &end));
319 10 : }
320 0 : } else if (evStr->getCond() == MQueryOp::Exists) {
321 : SAL_INFO("connectivity.mork", "MQueryOp::Exists; done");
322 0 : resultVector.push_back((currentValue.isEmpty()) ? sal_False : sal_True);
323 0 : } else if (evStr->getCond() == MQueryOp::DoesNotExist) {
324 : SAL_INFO("connectivity.mork", "MQueryOp::DoesNotExist; done");
325 0 : resultVector.push_back((currentValue.isEmpty()) ? sal_True : sal_False);
326 10 : }
327 : }
328 0 : else if ( (*evIter)->isExpr() ) {
329 : SAL_INFO("connectivity.mork", "Appending Subquery Expression");
330 0 : MQueryExpression* queryExpression = static_cast<MQueryExpression*> (*evIter);
331 : // recursive call
332 0 : ::std::vector<sal_Bool> subquery_result = entryMatchedByExpression(_aQuery, queryExpression, entry);
333 0 : MQueryExpression::bool_cond condition = queryExpression->getExpressionCondition();
334 0 : if (condition == MQueryExpression::OR) {
335 0 : bool result = false;
336 0 : for (::std::vector<sal_Bool>::iterator iter = subquery_result.begin(); iter != subquery_result.end(); ++iter) {
337 0 : result = result || *iter;
338 : }
339 0 : resultVector.push_back(result);
340 0 : } else if (condition == MQueryExpression::AND) {
341 0 : bool result = true;
342 0 : for (::std::vector<sal_Bool>::iterator iter = subquery_result.begin(); iter != subquery_result.end(); ++iter) {
343 0 : result = result && *iter;
344 : }
345 0 : resultVector.push_back(result);
346 : } else {
347 : OSL_FAIL("Unknown Expression Type");
348 0 : }
349 : }
350 : else {
351 : // Should never see this...
352 : SAL_WARN("connectivity.mork", "Unknown Expression Type!");
353 0 : _aQuery->getError().setResId(STR_ERROR_GET_ROW);
354 0 : return resultVector;
355 : }
356 : }
357 30 : return resultVector;
358 : }
359 :
360 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|