This is a preparation for merge into master, feature/mork branch is obsoslete and shouldn't be used any more. In context of this change the usage of old mozilla based mork driver depends on platform: all non windows platforms use this new mork driver, windows still uses mozilla. Because mozilla driver shipping was stripped on feature/mork branch for all platforms, the corresponding commits were changed prior to creating this change (the build file changes are reverted now). So the build and shipping of different mork driver implementation should be implemented from scratch: mozilla on windows, new mork dirver on all other platforms. Currently the new mork dirver is compiled (on all platforms), but not used. It can be tested with mork_helper executable. fdo#51004 Change-Id: Ib2413ab6856f163337aa311c4bf7b1182d6c6f63 Reviewed-on: https://gerrit.libreoffice.org/635 Reviewed-by: Miklos Vajna <vmiklos@suse.cz> Tested-by: Miklos Vajna <vmiklos@suse.cz>
415 lines
15 KiB
C++
415 lines
15 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
|
|
#include "MColumnAlias.hxx"
|
|
#include "MQueryHelper.hxx"
|
|
#include "MConnection.hxx"
|
|
|
|
#include "MorkParser.hxx"
|
|
#include <stdlib.h>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <string.h>
|
|
|
|
|
|
#include <connectivity/dbexception.hxx>
|
|
|
|
using namespace connectivity::mork;
|
|
using namespace connectivity;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::sdbc;
|
|
using namespace connectivity;
|
|
|
|
|
|
extern
|
|
::std::vector< sal_Bool > entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression* _aExpr, MQueryHelperResultEntry* entry);
|
|
|
|
MQueryHelperResultEntry::MQueryHelperResultEntry()
|
|
{
|
|
}
|
|
|
|
MQueryHelperResultEntry::~MQueryHelperResultEntry()
|
|
{
|
|
}
|
|
|
|
void MQueryHelperResultEntry::insert( const rtl::OString &key, rtl::OUString &value )
|
|
{
|
|
m_Fields[ key ] = value;
|
|
}
|
|
|
|
rtl::OUString MQueryHelperResultEntry::getValue( const rtl::OString &key ) const
|
|
{
|
|
FieldMap::const_iterator iter = m_Fields.find( key );
|
|
if ( iter == m_Fields.end() )
|
|
{
|
|
return rtl::OUString();
|
|
}
|
|
else
|
|
{
|
|
return iter->second;
|
|
}
|
|
}
|
|
|
|
void MQueryHelperResultEntry::setValue( const rtl::OString &key, const rtl::OUString & rValue)
|
|
{
|
|
// SAL_INFO("connectivity.mork", "MQueryHelper::setValue()" );
|
|
// SAL_INFO("connectivity.mork", "key: " << &key << " value: " << &rValue);
|
|
|
|
m_Fields[ key ] = rValue;
|
|
}
|
|
|
|
MQueryHelper::MQueryHelper(const OColumnAlias& _ca)
|
|
:m_nIndex( 0 )
|
|
,m_bHasMore( sal_True )
|
|
,m_bAtEnd( sal_False )
|
|
,m_rColumnAlias( _ca )
|
|
{
|
|
m_aResults.clear();
|
|
}
|
|
|
|
MQueryHelper::~MQueryHelper()
|
|
{
|
|
SAL_INFO("connectivity.mork", "MQueryHelper::~MQueryHelper()");
|
|
|
|
clear_results();
|
|
OSL_TRACE("OUT MQueryHelper::~MQueryHelper()");
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
void MQueryHelper::setAddressbook(::rtl::OUString &ab)
|
|
{
|
|
SAL_INFO("connectivity.mork", "MQueryHelper::setAddressbook()");
|
|
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
|
|
m_aAddressbook = ab;
|
|
|
|
OSL_TRACE("\tOUT MQuery::setAddressbook()");
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
void MQueryHelper::setExpression( MQueryExpression &_expr )
|
|
{
|
|
SAL_INFO("connectivity.mork", "MQueryHelper::setExpression()");
|
|
OSL_TRACE("IN MQueryHelper::setExpression()");
|
|
::osl::MutexGuard aGuard(m_aMutex);
|
|
|
|
m_aExpr = _expr;
|
|
|
|
OSL_TRACE("\tOUT MQuery::setExpression()");
|
|
}
|
|
|
|
void MQueryHelper::append(MQueryHelperResultEntry* resEnt)
|
|
{
|
|
// SAL_INFO("connectivity.mork", "MQueryHelper::append()");
|
|
|
|
if ( resEnt != NULL ) {
|
|
m_aResults.push_back( resEnt );
|
|
m_bAtEnd = sal_False;
|
|
}
|
|
}
|
|
|
|
void MQueryHelper::clear_results()
|
|
{
|
|
resultsArray::iterator iter = m_aResults.begin();
|
|
while ( iter != m_aResults.end() ) {
|
|
delete (*iter);
|
|
++iter;
|
|
}
|
|
m_aResults.clear();
|
|
}
|
|
|
|
void MQueryHelper::reset()
|
|
{
|
|
m_nIndex = 0;
|
|
m_bHasMore = sal_True;
|
|
m_bAtEnd = sal_False;
|
|
clear_results();
|
|
}
|
|
|
|
MQueryHelperResultEntry* MQueryHelper::next()
|
|
{
|
|
MQueryHelperResultEntry* result;
|
|
sal_uInt32 index;
|
|
|
|
m_aMutex.acquire();
|
|
index = m_nIndex;
|
|
m_aMutex.release();
|
|
|
|
result = getByIndex( index + 1) ; // Add 1 as Row is numbered from 1 to N
|
|
|
|
if ( result ) {
|
|
m_aMutex.acquire();
|
|
m_nIndex++;
|
|
m_aMutex.release();
|
|
}
|
|
|
|
return( result );
|
|
}
|
|
|
|
MQueryHelperResultEntry*
|
|
MQueryHelper::getByIndex(sal_uInt32 nRow)
|
|
{
|
|
// Row numbers are from 1 to N, need to ensure this, and then
|
|
// substract 1
|
|
if ( nRow < 1 ) {
|
|
return( NULL );
|
|
}
|
|
return m_aResults[nRow -1];
|
|
}
|
|
|
|
sal_Int32 MQueryHelper::getResultCount() const
|
|
{
|
|
// SAL_INFO("connectivity.mork", "MQueryHelper::getResultCount()" );
|
|
sal_Int32 result = static_cast<sal_Int32>(m_aResults.size());
|
|
// SAL_INFO("connectivity.mork", "result: " << result);
|
|
|
|
return result;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
sal_Bool MQueryHelper::queryComplete() const
|
|
{
|
|
return sal_True;
|
|
}
|
|
|
|
sal_Bool MQueryHelper::checkRowAvailable( sal_Int32 nDBRow )
|
|
{
|
|
/*
|
|
while (!queryComplete() && getResultCount() <= (sal_uInt32)nDBRow)
|
|
{
|
|
if ( !m_aQueryHelper->waitForRow( nDBRow ) ) {
|
|
m_aError = m_aQueryHelper->getError();
|
|
return( sal_False );
|
|
}
|
|
}
|
|
*/
|
|
return( getResultCount() > nDBRow );
|
|
}
|
|
|
|
|
|
sal_Bool MQueryHelper::getRowValue( ORowSetValue& rValue, sal_Int32 nDBRow,const rtl::OUString& aDBColumnName, sal_Int32 nType )
|
|
{
|
|
SAL_INFO("connectivity.mork", "MQueryHelper::getRowValue()" );
|
|
MQueryHelperResultEntry* xResEntry = getByIndex( nDBRow );
|
|
|
|
OSL_ENSURE( xResEntry != NULL, "xResEntry == NULL");
|
|
if (xResEntry == NULL )
|
|
{
|
|
rValue.setNull();
|
|
return sal_False;
|
|
}
|
|
switch ( nType )
|
|
{
|
|
case DataType::VARCHAR:
|
|
rValue = xResEntry->getValue( m_rColumnAlias.getProgrammaticNameOrFallbackToUTF8Alias( aDBColumnName ) );
|
|
break;
|
|
|
|
default:
|
|
rValue.setNull();
|
|
break;
|
|
}
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
sal_Int32 MQueryHelper::executeQuery(OConnection* xConnection)
|
|
{
|
|
SAL_INFO("connectivity.mork", "MQueryHelper::executeQuery()" );
|
|
reset();
|
|
|
|
//dumpExpression(this, &m_aExpr);
|
|
MorkTableMap::iterator tableIter;
|
|
MorkTableMap *Tables = xConnection->getMorkParser()->getTables( 0x80 );
|
|
MorkRowMap *Rows = 0;
|
|
MorkRowMap::iterator rowIter;
|
|
|
|
for ( tableIter = Tables->begin(); tableIter != Tables->end(); tableIter++ )
|
|
{
|
|
// Iterate all tables
|
|
for ( tableIter = Tables->begin(); tableIter != Tables->end(); tableIter++ )
|
|
{
|
|
if (tableIter->first != 1) break;
|
|
Rows = xConnection->getMorkParser()->getRows( 0x80, &tableIter->second );
|
|
if ( Rows )
|
|
{
|
|
// Iterate all rows
|
|
for ( rowIter = Rows->begin(); rowIter != Rows->end(); rowIter++ )
|
|
{
|
|
MQueryHelperResultEntry* entry = new MQueryHelperResultEntry();
|
|
for (MorkCells::iterator CellsIter = rowIter->second.begin();
|
|
CellsIter != rowIter->second.end(); CellsIter++ )
|
|
{
|
|
std::string column = xConnection->getMorkParser()->getColumn(CellsIter->first);
|
|
std::string value = xConnection->getMorkParser()->getValue(CellsIter->second);
|
|
|
|
//SAL_INFO("connectivity.mork", "key: " << column << " value: " << value);
|
|
|
|
OString key(column.c_str(), static_cast<sal_Int32>(column.size()));
|
|
OString valueOString(value.c_str(), static_cast<sal_Int32>(value.size()));
|
|
rtl::OUString valueOUString = ::rtl::OStringToOUString( valueOString, RTL_TEXTENCODING_UTF8 );
|
|
entry->setValue(key, valueOUString);
|
|
}
|
|
::std::vector< sal_Bool > vector = entryMatchedByExpression(this, &m_aExpr, entry);
|
|
sal_Bool result = sal_True;
|
|
for (::std::vector<sal_Bool>::iterator iter = vector.begin(); iter != vector.end(); ++iter) {
|
|
result = result && *iter;
|
|
}
|
|
if (result) {
|
|
append(entry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
::std::vector< sal_Bool > entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression* _aExpr, MQueryHelperResultEntry* entry)
|
|
{
|
|
::std::vector< sal_Bool > resultVector;
|
|
MQueryExpression::ExprVector::iterator evIter;
|
|
for( evIter = _aExpr->getExpressions().begin();
|
|
evIter != _aExpr->getExpressions().end();
|
|
++evIter )
|
|
{
|
|
if ( (*evIter)->isStringExpr() ) {
|
|
MQueryExpressionString* evStr = static_cast<MQueryExpressionString*> (*evIter);
|
|
|
|
// Set the 'name' property of the boolString.
|
|
// Check if it's an alias first...
|
|
rtl::OString attrName = _aQuery->getColumnAlias().getProgrammaticNameOrFallbackToUTF8Alias( evStr->getName() );
|
|
//OSL_TRACE("Name = %s ;", attrName.getStr() );
|
|
SAL_INFO("connectivity.mork", "Name = " << attrName.getStr());
|
|
// Set the 'matchType' property of the boolString. Check for equal length.
|
|
sal_Bool requiresValue = sal_True;
|
|
switch(evStr->getCond()) {
|
|
case MQueryOp::Exists:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::Exists; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::Exists);
|
|
requiresValue = sal_False;
|
|
break;
|
|
case MQueryOp::DoesNotExist:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::DoesNotExist; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::DoesNotExist);
|
|
requiresValue = sal_False;
|
|
break;
|
|
case MQueryOp::Contains:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::Contains; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::Contains);
|
|
break;
|
|
case MQueryOp::DoesNotContain:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::DoesNotContain; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::DoesNotContain);
|
|
break;
|
|
case MQueryOp::Is:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::Is; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::Is);
|
|
break;
|
|
case MQueryOp::IsNot:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::IsNot; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::IsNot);
|
|
break;
|
|
case MQueryOp::BeginsWith:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::BeginsWith; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::BeginsWith);
|
|
break;
|
|
case MQueryOp::EndsWith:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::EndsWith; done");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::EndsWith);
|
|
break;
|
|
case MQueryOp::SoundsLike:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::SoundsLike; TODO");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::SoundsLike);
|
|
break;
|
|
case MQueryOp::RegExp:
|
|
SAL_INFO("connectivity.mork", "MQueryOp::RegExp; TODO");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::RegExp);
|
|
break;
|
|
default:
|
|
SAL_INFO("connectivity.mork", "(default) MQueryOp::Is; ");
|
|
//boolString->SetCondition(nsIAbBooleanConditionTypes::Is);
|
|
break;
|
|
}
|
|
rtl::OUString currentValue = entry->getValue(attrName);
|
|
// Set the 'matchValue' property of the boolString. Value returned in unicode.
|
|
if ( requiresValue )
|
|
{
|
|
SAL_INFO("connectivity.mork", "Value = " << evStr->getValue() );
|
|
rtl::OUString searchedValue = evStr->getValue();
|
|
if (evStr->getCond() == MQueryOp::Is) {
|
|
resultVector.push_back((currentValue == searchedValue) ? sal_True : sal_False);
|
|
} else if (evStr->getCond() == MQueryOp::IsNot) {
|
|
resultVector.push_back((currentValue == searchedValue) ? sal_False : sal_True);
|
|
} else if (evStr->getCond() == MQueryOp::EndsWith) {
|
|
resultVector.push_back((currentValue.endsWith(searchedValue)) ? sal_True : sal_False);
|
|
} else if (evStr->getCond() == MQueryOp::BeginsWith) {
|
|
resultVector.push_back((currentValue.indexOf(searchedValue) == 0) ? sal_True : sal_False);
|
|
} else if (evStr->getCond() == MQueryOp::Contains) {
|
|
resultVector.push_back((currentValue.indexOf(searchedValue) == -1) ? sal_False : sal_True);
|
|
} else if (evStr->getCond() == MQueryOp::DoesNotContain) {
|
|
resultVector.push_back((currentValue.indexOf(searchedValue) == -1) ? sal_True : sal_False);
|
|
} else {
|
|
OSL_FAIL("not yet implemented");
|
|
}
|
|
}
|
|
|
|
// Find it and change it ;-)
|
|
// class rtl::OUString "has no element named" isEmtpy
|
|
if (evStr->getCond() == MQueryOp::Exists) {
|
|
resultVector.push_back((currentValue.getLength() == 0) ? sal_False : sal_True);
|
|
} else if (evStr->getCond() == MQueryOp::DoesNotExist) {
|
|
resultVector.push_back((currentValue.getLength() == 0) ? sal_True : sal_False);
|
|
}
|
|
}
|
|
else if ( (*evIter)->isExpr() ) {
|
|
SAL_INFO("connectivity.mork", "Appending Subquery Expression");
|
|
MQueryExpression* queryExpression = static_cast<MQueryExpression*> (*evIter);
|
|
::std::vector<sal_Bool> subquery_result = entryMatchedByExpression(_aQuery, queryExpression, entry);
|
|
MQueryExpression::bool_cond condition = queryExpression->getExpressionCondition();
|
|
if (condition == MQueryExpression::OR) {
|
|
sal_Bool result = sal_False;
|
|
for (::std::vector<sal_Bool>::iterator iter = subquery_result.begin(); iter != subquery_result.end(); ++iter) {
|
|
result = result || *iter;
|
|
}
|
|
resultVector.push_back(result);
|
|
} else if (condition == MQueryExpression::AND) {
|
|
sal_Bool result = sal_True;
|
|
for (::std::vector<sal_Bool>::iterator iter = subquery_result.begin(); iter != subquery_result.end(); ++iter) {
|
|
result = result && *iter;
|
|
}
|
|
resultVector.push_back(result);
|
|
} else {
|
|
OSL_FAIL("Unknown Expression Type");
|
|
}
|
|
}
|
|
else {
|
|
// Should never see this...
|
|
// OSL_FAIL("Unknown Expression Type!");
|
|
SAL_WARN("connectivity.mork", "Unknown Expression Type!");
|
|
return resultVector;
|
|
}
|
|
}
|
|
return resultVector;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|