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 "MColumnAlias.hxx"
22 #include "MQueryHelper.hxx"
23 #include "MConnection.hxx"
25 #include "MorkParser.hxx"
33 #include "resource/mork_res.hrc"
34 #include "resource/common_res.hrc"
36 #include <connectivity/dbexception.hxx>
37 #include <unotools/textsearch.hxx>
39 using namespace connectivity::mork
;
40 using namespace connectivity
;
41 using namespace ::com::sun::star::beans
;
42 using namespace ::com::sun::star::sdbc
;
46 ::std::vector
< sal_Bool
> entryMatchedByExpression(MQueryHelper
* _aQuery
, MQueryExpression
* _aExpr
, MQueryHelperResultEntry
* entry
);
48 MQueryHelperResultEntry::MQueryHelperResultEntry()
52 MQueryHelperResultEntry::~MQueryHelperResultEntry()
56 OUString
MQueryHelperResultEntry::getValue( const OString
&key
) const
58 FieldMap::const_iterator iter
= m_Fields
.find( key
);
59 if ( iter
== m_Fields
.end() )
69 void MQueryHelperResultEntry::setValue( const OString
&key
, const OUString
& rValue
)
71 // SAL_INFO("connectivity.mork", "MQueryHelper::setValue()" );
72 // SAL_INFO("connectivity.mork", "key: " << &key << " value: " << &rValue);
74 m_Fields
[ key
] = rValue
;
77 MQueryHelper::MQueryHelper(const OColumnAlias
& _ca
)
79 ,m_bHasMore( sal_True
)
80 ,m_bAtEnd( sal_False
)
81 ,m_rColumnAlias( _ca
)
87 MQueryHelper::~MQueryHelper()
89 SAL_INFO("connectivity.mork", "MQueryHelper::~MQueryHelper()");
92 OSL_TRACE("OUT MQueryHelper::~MQueryHelper()");
95 // -------------------------------------------------------------------------
96 void MQueryHelper::setAddressbook(OUString
&ab
)
98 SAL_INFO("connectivity.mork", "MQueryHelper::setAddressbook()");
100 ::osl::MutexGuard
aGuard(m_aMutex
);
104 OSL_TRACE("\tOUT MQuery::setAddressbook()");
106 // -------------------------------------------------------------------------
107 void MQueryHelper::setExpression( MQueryExpression
&_expr
)
109 SAL_INFO("connectivity.mork", "MQueryHelper::setExpression()");
110 OSL_TRACE("IN MQueryHelper::setExpression()");
111 ::osl::MutexGuard
aGuard(m_aMutex
);
115 OSL_TRACE("\tOUT MQuery::setExpression()");
118 void MQueryHelper::append(MQueryHelperResultEntry
* resEnt
)
120 // SAL_INFO("connectivity.mork", "MQueryHelper::append()");
122 if ( resEnt
!= NULL
) {
123 m_aResults
.push_back( resEnt
);
124 m_bAtEnd
= sal_False
;
128 void MQueryHelper::clear_results()
130 resultsArray::iterator iter
= m_aResults
.begin();
131 while ( iter
!= m_aResults
.end() ) {
138 void MQueryHelper::reset()
141 m_bHasMore
= sal_True
;
142 m_bAtEnd
= sal_False
;
147 MQueryHelperResultEntry
*
148 MQueryHelper::getByIndex(sal_uInt32 nRow
)
150 // Row numbers are from 1 to N, need to ensure this, and then
155 return m_aResults
[nRow
-1];
158 sal_Int32
MQueryHelper::getResultCount() const
160 // SAL_INFO("connectivity.mork", "MQueryHelper::getResultCount()" );
161 sal_Int32 result
= static_cast<sal_Int32
>(m_aResults
.size());
162 // SAL_INFO("connectivity.mork", "result: " << result);
167 // -------------------------------------------------------------------------
169 sal_Bool
MQueryHelper::queryComplete() const
174 sal_Bool
MQueryHelper::checkRowAvailable( sal_Int32 nDBRow
)
177 while (!queryComplete() && getResultCount() <= (sal_uInt32)nDBRow)
179 if ( !m_aQueryHelper->waitForRow( nDBRow ) ) {
180 m_aError = m_aQueryHelper->getError();
185 return( getResultCount() > nDBRow
);
189 sal_Bool
MQueryHelper::getRowValue( ORowSetValue
& rValue
, sal_Int32 nDBRow
,const OUString
& aDBColumnName
, sal_Int32 nType
)
191 SAL_INFO("connectivity.mork", "MQueryHelper::getRowValue()" );
192 MQueryHelperResultEntry
* xResEntry
= getByIndex( nDBRow
);
194 OSL_ENSURE( xResEntry
!= NULL
, "xResEntry == NULL");
195 if (xResEntry
== NULL
)
202 case DataType::VARCHAR
:
203 rValue
= xResEntry
->getValue( m_rColumnAlias
.getProgrammaticNameOrFallbackToUTF8Alias( aDBColumnName
) );
214 sal_Int32
MQueryHelper::executeQuery(OConnection
* xConnection
)
216 SAL_INFO("connectivity.mork", "MQueryHelper::executeQuery()" );
219 OString oStringTable
= OUStringToOString( m_aAddressbook
, RTL_TEXTENCODING_UTF8
);
220 std::set
<int> listRecords
;
221 bool handleListTable
= false;
223 // check if we are retrieving the default table
224 if (oStringTable
!= "AddressBook")
226 handleListTable
= true;
227 // retrieve row ids for that list table
228 std::string listTable
= oStringTable
.getStr();
229 xConnection
->getMorkParser()->getRecordKeysForListTable(listTable
, listRecords
);
231 MorkTableMap::iterator tableIter
;
232 MorkTableMap
*Tables
= xConnection
->getMorkParser()->getTables( 0x80 );
233 MorkRowMap
*Rows
= 0;
234 MorkRowMap::iterator rowIter
;
236 // Iterate all tables
237 for ( tableIter
= Tables
->begin(); tableIter
!= Tables
->end(); ++tableIter
)
239 if (tableIter
->first
!= 1) break;
240 Rows
= xConnection
->getMorkParser()->getRows( 0x80, &tableIter
->second
);
244 for ( rowIter
= Rows
->begin(); rowIter
!= Rows
->end(); ++rowIter
)
246 // list specific table
247 // only retrieve rowIds that belong to that list table.
250 int rowId
= rowIter
->first
;
251 // belongs this row id to the list table?
252 if (listRecords
.end() == std::find(listRecords
.begin(), listRecords
.end(), rowId
))
259 MQueryHelperResultEntry
* entry
= new MQueryHelperResultEntry();
260 for (MorkCells::iterator CellsIter
= rowIter
->second
.begin();
261 CellsIter
!= rowIter
->second
.end(); ++CellsIter
)
263 std::string column
= xConnection
->getMorkParser()->getColumn(CellsIter
->first
);
264 std::string value
= xConnection
->getMorkParser()->getValue(CellsIter
->second
);
265 OString
key(column
.c_str(), static_cast<sal_Int32
>(column
.size()));
266 OString
valueOString(value
.c_str(), static_cast<sal_Int32
>(value
.size()));
267 OUString valueOUString
= OStringToOUString( valueOString
, RTL_TEXTENCODING_UTF8
);
268 entry
->setValue(key
, valueOUString
);
270 ::std::vector
< sal_Bool
> vector
= entryMatchedByExpression(this, &m_aExpr
, entry
);
271 sal_Bool result
= sal_True
;
272 for (::std::vector
<sal_Bool
>::iterator iter
= vector
.begin(); iter
!= vector
.end(); ++iter
)
274 result
= result
&& *iter
;
290 ::std::vector
< sal_Bool
> entryMatchedByExpression(MQueryHelper
* _aQuery
, MQueryExpression
* _aExpr
, MQueryHelperResultEntry
* entry
)
292 ::std::vector
< sal_Bool
> resultVector
;
293 MQueryExpression::ExprVector::iterator evIter
;
294 for( evIter
= _aExpr
->getExpressions().begin();
295 evIter
!= _aExpr
->getExpressions().end();
298 if ( (*evIter
)->isStringExpr() ) {
299 MQueryExpressionString
* evStr
= static_cast<MQueryExpressionString
*> (*evIter
);
300 // Set the 'name' property of the boolString.
301 OString attrName
= _aQuery
->getColumnAlias().getProgrammaticNameOrFallbackToUTF8Alias( evStr
->getName() );
302 SAL_INFO("connectivity.mork", "Name = " << attrName
.getStr());
303 sal_Bool requiresValue
= sal_True
;
304 OUString currentValue
= entry
->getValue(attrName
);
305 if (evStr
->getCond() == MQueryOp::Exists
|| evStr
->getCond() == MQueryOp::DoesNotExist
)
307 requiresValue
= sal_False
;
311 SAL_INFO("connectivity.mork", "Value = " << evStr
->getValue() );
312 OUString searchedValue
= evStr
->getValue();
313 if (evStr
->getCond() == MQueryOp::Is
) {
314 SAL_INFO("connectivity.mork", "MQueryOp::Is; done");
315 resultVector
.push_back((currentValue
== searchedValue
) ? sal_True
: sal_False
);
316 } else if (evStr
->getCond() == MQueryOp::IsNot
) {
317 SAL_INFO("connectivity.mork", "MQueryOp::IsNot; done");
318 resultVector
.push_back((currentValue
== searchedValue
) ? sal_False
: sal_True
);
319 } else if (evStr
->getCond() == MQueryOp::EndsWith
) {
320 SAL_INFO("connectivity.mork", "MQueryOp::EndsWith; done");
321 resultVector
.push_back((currentValue
.endsWith(searchedValue
)) ? sal_True
: sal_False
);
322 } else if (evStr
->getCond() == MQueryOp::BeginsWith
) {
323 SAL_INFO("connectivity.mork", "MQueryOp::BeginsWith; done");
324 resultVector
.push_back((currentValue
.indexOf(searchedValue
) == 0) ? sal_True
: sal_False
);
325 } else if (evStr
->getCond() == MQueryOp::Contains
) {
326 SAL_INFO("connectivity.mork", "MQueryOp::Contains; done");
327 resultVector
.push_back((currentValue
.indexOf(searchedValue
) == -1) ? sal_False
: sal_True
);
328 } else if (evStr
->getCond() == MQueryOp::DoesNotContain
) {
329 SAL_INFO("connectivity.mork", "MQueryOp::DoesNotContain; done");
330 resultVector
.push_back((currentValue
.indexOf(searchedValue
) == -1) ? sal_True
: sal_False
);
331 } else if (evStr
->getCond() == MQueryOp::RegExp
) {
332 SAL_INFO("connectivity.mork", "MQueryOp::RegExp; done");
333 utl::SearchParam
param(
334 searchedValue
, utl::SearchParam::SRCH_REGEXP
);
335 utl::TextSearch
ts(param
, LANGUAGE_DONTKNOW
);
337 sal_Int32 end
= currentValue
.getLength();
338 resultVector
.push_back(
339 ts
.SearchForward(currentValue
, &start
, &end
));
341 } else if (evStr
->getCond() == MQueryOp::Exists
) {
342 SAL_INFO("connectivity.mork", "MQueryOp::Exists; done");
343 resultVector
.push_back((currentValue
.isEmpty()) ? sal_False
: sal_True
);
344 } else if (evStr
->getCond() == MQueryOp::DoesNotExist
) {
345 SAL_INFO("connectivity.mork", "MQueryOp::DoesNotExist; done");
346 resultVector
.push_back((currentValue
.isEmpty()) ? sal_True
: sal_False
);
349 else if ( (*evIter
)->isExpr() ) {
350 SAL_INFO("connectivity.mork", "Appending Subquery Expression");
351 MQueryExpression
* queryExpression
= static_cast<MQueryExpression
*> (*evIter
);
353 ::std::vector
<sal_Bool
> subquery_result
= entryMatchedByExpression(_aQuery
, queryExpression
, entry
);
354 MQueryExpression::bool_cond condition
= queryExpression
->getExpressionCondition();
355 if (condition
== MQueryExpression::OR
) {
356 sal_Bool result
= sal_False
;
357 for (::std::vector
<sal_Bool
>::iterator iter
= subquery_result
.begin(); iter
!= subquery_result
.end(); ++iter
) {
358 result
= result
|| *iter
;
360 resultVector
.push_back(result
);
361 } else if (condition
== MQueryExpression::AND
) {
362 sal_Bool result
= sal_True
;
363 for (::std::vector
<sal_Bool
>::iterator iter
= subquery_result
.begin(); iter
!= subquery_result
.end(); ++iter
) {
364 result
= result
&& *iter
;
366 resultVector
.push_back(result
);
368 OSL_FAIL("Unknown Expression Type");
372 // Should never see this...
373 SAL_WARN("connectivity.mork", "Unknown Expression Type!");
374 _aQuery
->getError().setResId(STR_ERROR_GET_ROW
);
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */