Files
libreoffice/connectivity/source/drivers/mork/MResultSet.cxx
David Ostrovsky 77e4adbe47 mork driver implementation
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>
2012-09-18 08:30:01 +00:00

2302 lines
87 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 <com/sun/star/sdbc/DataType.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <comphelper/property.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <comphelper/extract.hxx>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/sdbc/ResultSetType.hpp>
#include <com/sun/star/sdbc/FetchDirection.hpp>
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
#include <comphelper/types.hxx>
#include <connectivity/dbexception.hxx>
#include <connectivity/dbtools.hxx>
#include <TSortIndex.hxx>
#include <rtl/string.hxx>
#include <vector>
#include <algorithm>
#include "MResultSet.hxx"
#include "MResultSetMetaData.hxx"
#include "FDatabaseMetaDataResultSet.hxx"
#include "resource/mork_res.hrc"
#include "resource/common_res.hrc"
#if OSL_DEBUG_LEVEL > 0
# define OUtoCStr( x ) ( ::rtl::OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
#else /* OSL_DEBUG_LEVEL */
# define OUtoCStr( x ) ("dummy")
#endif /* OSL_DEBUG_LEVEL */
using namespace ::comphelper;
using namespace connectivity;
using namespace connectivity::mork;
using namespace ::cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::container;
using namespace com::sun::star::io;
using namespace com::sun::star::util;
//------------------------------------------------------------------------------
// IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
::rtl::OUString SAL_CALL OResultSet::getImplementationName( ) throw ( RuntimeException) \
{
return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbcx.mork.ResultSet"));
}
// -------------------------------------------------------------------------
Sequence< ::rtl::OUString > SAL_CALL OResultSet::getSupportedServiceNames( ) throw( RuntimeException)
{
::com::sun::star::uno::Sequence< ::rtl::OUString > aSupported(2);
aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbc.ResultSet"));
aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdbcx.ResultSet"));
return aSupported;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw( RuntimeException)
{
Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
const ::rtl::OUString* pSupported = aSupported.getConstArray();
const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
;
return pSupported != pEnd;
}
// -------------------------------------------------------------------------
OResultSet::OResultSet(OCommonStatement* pStmt, const ::boost::shared_ptr< connectivity::OSQLParseTreeIterator >& _pSQLIterator )
: OResultSet_BASE(m_aMutex)
,OPropertySetHelper(OResultSet_BASE::rBHelper)
,m_pStatement(pStmt)
,m_xStatement(*pStmt)
,m_xMetaData(NULL)
,m_nRowPos(0)
,m_nOldRowPos(0)
,m_nFetchSize(0)
,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE)
,m_nFetchDirection(FetchDirection::FORWARD)
,m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE)
,m_pSQLIterator( _pSQLIterator )
,m_pParseTree( _pSQLIterator->getParseTree() )
//,m_aQuery( pStmt->getOwnConnection()->getColumnAlias() )
,m_aQueryHelper(pStmt->getOwnConnection()->getColumnAlias())
,m_pTable(NULL)
,m_CurrentRowCount(0)
,m_nParamIndex(0)
,m_bIsAlwaysFalseQuery(sal_False)
,m_pKeySet(NULL)
,m_nNewRow(0)
,m_nUpdatedRow(0)
,m_RowStates(0)
,m_bIsReadOnly(-1)
{
//m_aQuery.setMaxNrOfReturns(pStmt->getOwnConnection()->getMaxResultRecords());
}
// -------------------------------------------------------------------------
OResultSet::~OResultSet()
{
}
// -------------------------------------------------------------------------
void OResultSet::disposing(void)
{
OPropertySetHelper::disposing();
::osl::MutexGuard aGuard(m_aMutex);
m_xStatement.clear();
m_xMetaData.clear();
m_pParseTree = NULL;
m_xColumns = NULL;
m_xParamColumns = NULL;
m_pKeySet = NULL;
if(m_pTable)
{
m_pTable->release();
m_pTable = NULL;
}
}
// -------------------------------------------------------------------------
Any SAL_CALL OResultSet::queryInterface( const Type & rType ) throw(RuntimeException)
{
Any aRet = OPropertySetHelper::queryInterface(rType);
if(!aRet.hasValue())
aRet = OResultSet_BASE::queryInterface(rType);
return aRet;
}
// -------------------------------------------------------------------------
Sequence< Type > SAL_CALL OResultSet::getTypes( ) throw( RuntimeException)
{
OTypeCollection aTypes( ::getCppuType( (const Reference< ::com::sun::star::beans::XMultiPropertySet > *)0 ),
::getCppuType( (const Reference< ::com::sun::star::beans::XFastPropertySet > *)0 ),
::getCppuType( (const Reference< ::com::sun::star::beans::XPropertySet > *)0 ));
return ::comphelper::concatSequences(aTypes.getTypes(),OResultSet_BASE::getTypes());
}
// -------------------------------------------------------------------------
void OResultSet::methodEntry()
{
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
if ( !m_pTable )
{
OSL_FAIL( "OResultSet::methodEntry: looks like we're disposed, but how is this possible?" );
throw DisposedException( ::rtl::OUString(), *this );
}
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OResultSet::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
// find the first column with the name columnName
Reference< XResultSetMetaData > xMeta = getMetaData();
sal_Int32 nLen = xMeta->getColumnCount();
sal_Int32 i = 1;
for(;i<=nLen;++i)
if(xMeta->isCaseSensitive(i) ? columnName == xMeta->getColumnName(i) :
columnName.equalsIgnoreAsciiCase(xMeta->getColumnName(i)))
break;
return i;
}
// -------------------------------------------------------------------------
Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::getBoolean( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
m_bWasNull = sal_True;
return sal_False;
}
// -------------------------------------------------------------------------
sal_Int8 SAL_CALL OResultSet::getByte( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return 0;
}
// -------------------------------------------------------------------------
Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return Sequence< sal_Int8 >();
}
// -------------------------------------------------------------------------
Date SAL_CALL OResultSet::getDate( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return Date();
}
// -------------------------------------------------------------------------
double SAL_CALL OResultSet::getDouble( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return 0.0;
}
// -------------------------------------------------------------------------
float SAL_CALL OResultSet::getFloat( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return 0;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OResultSet::getInt( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return 0;
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OResultSet::getRow( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::getRow, return = %u", m_nRowPos );
return m_nRowPos;
}
// -------------------------------------------------------------------------
sal_Int64 SAL_CALL OResultSet::getLong( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return sal_Int64();
}
// -------------------------------------------------------------------------
Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
if(!m_xMetaData.is())
m_xMetaData = new OResultSetMetaData(
m_pSQLIterator->getSelectColumns(), m_pSQLIterator->getTables().begin()->first ,m_pTable,determineReadOnly());
return m_xMetaData;
}
// -------------------------------------------------------------------------
Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
Reference< XBlob > SAL_CALL OResultSet::getBlob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return NULL;
}
// -------------------------------------------------------------------------
Any SAL_CALL OResultSet::getObject( sal_Int32 /*columnIndex*/, const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException)
{
return Any();
}
// -------------------------------------------------------------------------
sal_Int16 SAL_CALL OResultSet::getShort( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
return 0;
}
// -------------------------------------------------------------------------
void OResultSet::checkIndex(sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException)
{
if(columnIndex <= 0 || columnIndex > (sal_Int32)m_xColumns->get().size())
::dbtools::throwInvalidIndexException(*this);
}
// -------------------------------------------------------------------------
sal_uInt32 OResultSet::currentRowCount()
{
if ( m_bIsAlwaysFalseQuery )
return 0;
//return 0;//m_aQuery.getRealRowCount() - deletedCount();
// new implementation
return m_aQueryHelper.getResultCount();
}
// -------------------------------------------------------------------------
sal_Bool OResultSet::fetchCurrentRow( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("fetchCurrentRow, m_nRowPos = %u", m_nRowPos );
return fetchRow(getCurrentCardNumber());
}
// -------------------------------------------------------------------------
sal_Bool OResultSet::pushCard(sal_uInt32 /*cardNumber*/) throw(SQLException, RuntimeException)
{
SAL_INFO("connectivity.mork", "=> OResultSet::pushCard()" );
return sal_True;
/*
if (cardNumber == 0)
return sal_True;
// Check whether we are storing the updated row
if ( (m_aRow->get())[0].isNull() || (sal_Int32)(m_aRow->get())[0] != (sal_Int32)cardNumber )
return sal_False;
sal_Int32 nCount = m_aColumnNames.getLength();
m_aQuery.setRowStates(cardNumber,m_RowStates);
for( sal_Int32 i = 1; i <= nCount; i++ )
{
if ( (m_aRow->get())[i].isBound() )
{
//
// Everything in the addressbook is a string!
//
if ( !m_aQuery.setRowValue( (m_aRow->get())[i], cardNumber, m_aColumnNames[i-1], DataType::VARCHAR ))
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQuery.getError(), *this );
}
}
}
return sal_True;
*/
}
// -------------------------------------------------------------------------
sal_Bool OResultSet::fetchRow(sal_Int32 cardNumber,sal_Bool bForceReload) throw(SQLException, RuntimeException)
{
SAL_INFO("connectivity.mork", "=> OResultSet::fetchRow()" );
OSL_TRACE("fetchRow, cardNumber = %u", cardNumber );
if (!bForceReload)
{
// Check whether we've already fetched the row...
if ( !(m_aRow->get())[0].isNull() && (sal_Int32)(m_aRow->get())[0] == (sal_Int32)cardNumber )
return sal_True;
//Check whether the old row has been changed
if (cardNumber == m_nUpdatedRow)
{
//write back the changes first
if (!pushCard(cardNumber)) //error write back the changes
throw SQLException();
}
}
// else
// m_aQuery.resyncRow(cardNumber);
if ( validRow( cardNumber ) == sal_False )
return sal_False;
(m_aRow->get())[0] = (sal_Int32)cardNumber;
sal_Int32 nCount = m_aColumnNames.getLength();
//m_RowStates = m_aQuery.getRowStates(cardNumber);
for( sal_Int32 i = 1; i <= nCount; i++ )
{
if ( (m_aRow->get())[i].isBound() )
{
//
// Everything in the addressbook is a string!
//
if ( !m_aQueryHelper.getRowValue( (m_aRow->get())[i], cardNumber, m_aColumnNames[i-1], DataType::VARCHAR ))
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
}
}
return sal_True;
}
// -------------------------------------------------------------------------
const ORowSetValue& OResultSet::getValue(sal_Int32 cardNumber, sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
{
if ( fetchRow( cardNumber ) == sal_False )
{
OSL_FAIL("fetchRow() returned False" );
m_bWasNull = sal_True;
return *ODatabaseMetaDataResultSet::getEmptyValue();
}
m_bWasNull = (m_aRow->get())[columnIndex].isNull();
return (m_aRow->get())[columnIndex];
}
// -------------------------------------------------------------------------
::rtl::OUString SAL_CALL OResultSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
OSL_ENSURE(columnIndex <= (sal_Int32)m_xColumns->get().size(), "Trying to access invalid columns number");
checkIndex( columnIndex );
// If this query was sorted then we should have a valid KeySet, so use it
return getValue(getCurrentCardNumber(), mapColumn( columnIndex ) );
}
// -------------------------------------------------------------------------
Time SAL_CALL OResultSet::getTime( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return Time();
}
// -------------------------------------------------------------------------
DateTime SAL_CALL OResultSet::getTimestamp( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return DateTime();
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::isBeforeFirst( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
// here you have to implement your movements
// return true means there is no data
OSL_TRACE("In/Out: OResultSet::isBeforeFirst" );
return( m_nRowPos < 1 );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::isAfterLast( ) throw(SQLException, RuntimeException)
{
SAL_WARN("connectivity.mork", "OResultSet::isAfterLast() NOT IMPLEMENTED!");
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::isAfterLast" );
// return sal_True;
return m_nRowPos > currentRowCount() && m_aQueryHelper.queryComplete();
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::isFirst( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::isFirst" );
return m_nRowPos == 1;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::isLast( ) throw(SQLException, RuntimeException)
{
SAL_WARN("connectivity.mork", "OResultSet::isLast() NOT IMPLEMENTED!");
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::isLast" );
// return sal_True;
return m_nRowPos == currentRowCount() && m_aQueryHelper.queryComplete();
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::beforeFirst( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
// move before the first row so that isBeforeFirst returns false
OSL_TRACE("In/Out: OResultSet::beforeFirst" );
if ( first() )
previous();
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::afterLast( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::afterLast" );
if(last())
next();
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::close() throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::close" );
OSL_FAIL( "OResultSet::close: going to dispose()" );
dispose();
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::first( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::first" );
return seekRow( FIRST_POS );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::last( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::last" );
return seekRow( LAST_POS );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::absolute" );
return seekRow( ABSOLUTE_POS, row );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::relative( sal_Int32 row ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::relative" );
return seekRow( RELATIVE_POS, row );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::previous( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::previous" );
return seekRow( PRIOR_POS );
}
// -------------------------------------------------------------------------
Reference< XInterface > SAL_CALL OResultSet::getStatement( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::getStatement" );
return m_xStatement;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::rowDeleted( ) throw(SQLException, RuntimeException)
{
SAL_WARN("connectivity.mork", "OResultSet::rowDeleted() NOT IMPLEMENTED!");
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::rowDeleted, m_RowStates=%u",m_RowStates );
return sal_True;//return ((m_RowStates & RowStates_Deleted) == RowStates_Deleted) ;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::rowInserted( ) throw(SQLException, RuntimeException)
{
SAL_WARN("connectivity.mork", "OResultSet::rowInserted() NOT IMPLEMENTED!");
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::rowInserted,m_RowStates=%u",m_RowStates );
return sal_True;//return ((m_RowStates & RowStates_Inserted) == RowStates_Inserted);
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::rowUpdated( ) throw(SQLException, RuntimeException)
{
SAL_WARN("connectivity.mork", "OResultSet::rowUpdated() NOT IMPLEMENTED!");
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::rowUpdated,m_RowStates=%u",m_RowStates );
return sal_True;// return ((m_RowStates & RowStates_Updated) == RowStates_Updated) ;
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::next( ) throw(SQLException, RuntimeException)
{
return seekRow( NEXT_POS );
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OResultSet::wasNull( ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
return m_bWasNull;
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::cancel( ) throw(RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("In/Out: OResultSet::cancel" );
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::clearWarnings( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::clearWarnings" );
}
// -------------------------------------------------------------------------
Any SAL_CALL OResultSet::getWarnings( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::getWarnings" );
return Any();
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::refreshRow( ) throw(SQLException, RuntimeException)
{
OSL_TRACE("In/Out: OResultSet::refreshRow" );
if (fetchRow(getCurrentCardNumber(),sal_True)) {
//force fetch current row will cause we lose all change to the current row
m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_REFRESH_ROW, *this );
}
}
// -------------------------------------------------------------------------
IPropertyArrayHelper* OResultSet::createArrayHelper( ) const
{
Sequence< Property > aProps(5);
Property* pProperties = aProps.getArray();
sal_Int32 nPos = 0;
DECL_PROP0(FETCHDIRECTION, sal_Int32);
DECL_PROP0(FETCHSIZE, sal_Int32);
DECL_BOOL_PROP1IMPL(ISBOOKMARKABLE) PropertyAttribute::READONLY);
DECL_PROP1IMPL(RESULTSETCONCURRENCY,sal_Int32) PropertyAttribute::READONLY);
DECL_PROP1IMPL(RESULTSETTYPE, sal_Int32) PropertyAttribute::READONLY);
return new OPropertyArrayHelper(aProps);
}
// -------------------------------------------------------------------------
IPropertyArrayHelper & OResultSet::getInfoHelper()
{
return *const_cast<OResultSet*>(this)->getArrayHelper();
}
// -------------------------------------------------------------------------
sal_Bool OResultSet::convertFastPropertyValue(
Any & /*rConvertedValue*/,
Any & /*rOldValue*/,
sal_Int32 nHandle,
const Any& /*rValue*/ )
throw (::com::sun::star::lang::IllegalArgumentException)
{
OSL_FAIL( "OResultSet::convertFastPropertyValue: not implemented!" );
switch(nHandle)
{
case PROPERTY_ID_ISBOOKMARKABLE:
case PROPERTY_ID_RESULTSETCONCURRENCY:
case PROPERTY_ID_RESULTSETTYPE:
throw ::com::sun::star::lang::IllegalArgumentException();
case PROPERTY_ID_FETCHDIRECTION:
case PROPERTY_ID_FETCHSIZE:
default:
;
}
return sal_False;
}
// -------------------------------------------------------------------------
void OResultSet::setFastPropertyValue_NoBroadcast(
sal_Int32 nHandle,
const Any& /*rValue*/
)
throw (Exception)
{
OSL_FAIL( "OResultSet::setFastPropertyValue_NoBroadcast: not implemented!" );
switch(nHandle)
{
case PROPERTY_ID_ISBOOKMARKABLE:
case PROPERTY_ID_RESULTSETCONCURRENCY:
case PROPERTY_ID_RESULTSETTYPE:
throw Exception();
case PROPERTY_ID_FETCHDIRECTION:
break;
case PROPERTY_ID_FETCHSIZE:
break;
default:
;
}
}
// -------------------------------------------------------------------------
void OResultSet::getFastPropertyValue(
Any& rValue,
sal_Int32 nHandle
) const
{
switch(nHandle)
{
case PROPERTY_ID_RESULTSETCONCURRENCY:
rValue <<= (sal_Int32)m_nResultSetConcurrency;
break;
case PROPERTY_ID_RESULTSETTYPE:
rValue <<= m_nResultSetType;
break;
case PROPERTY_ID_FETCHDIRECTION:
rValue <<= m_nFetchDirection;
break;
case PROPERTY_ID_FETCHSIZE:
rValue <<= m_nFetchSize;
break;
case PROPERTY_ID_ISBOOKMARKABLE:
const_cast< OResultSet* >( this )->determineReadOnly();
rValue <<= !m_bIsReadOnly;
break;
}
}
// -----------------------------------------------------------------------------
void SAL_CALL OResultSet::acquire() throw()
{
OResultSet_BASE::acquire();
}
// -----------------------------------------------------------------------------
void SAL_CALL OResultSet::release() throw()
{
OResultSet_BASE::release();
}
// -----------------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException)
{
return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
}
// -------------------------------------------------------------------------
void OResultSet::parseParameter( const OSQLParseNode* pNode, rtl::OUString& rMatchString )
{
OSL_ENSURE(pNode->count() > 0,"Error parsing parameter in Parse Tree");
OSQLParseNode *pMark = pNode->getChild(0);
// Initialize to empty string
rMatchString = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(""));
rtl::OUString aParameterName;
if (SQL_ISPUNCTUATION(pMark,"?")) {
aParameterName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?"));
}
else if (SQL_ISPUNCTUATION(pMark,":")) {
aParameterName = pNode->getChild(1)->getTokenValue();
}
// XXX - Now we know name, what's value????
m_nParamIndex ++;
OSL_TRACE("Parameter name [%d]: %s", m_nParamIndex,OUtoCStr(aParameterName) );
if ( m_aParameterRow.is() ) {
OSL_ENSURE( m_nParamIndex < (sal_Int32)m_aParameterRow->get().size() + 1, "More parameters than values found" );
rMatchString = (m_aParameterRow->get())[(sal_uInt16)m_nParamIndex];
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Prop Value : %s", OUtoCStr( rMatchString ) );
#endif
}
#if OSL_DEBUG_LEVEL > 0
else {
OSL_TRACE("Prop Value : Invalid ParameterRow!" );
}
#endif
}
void OResultSet::analyseWhereClause( const OSQLParseNode* parseTree,
MQueryExpression &queryExpression)
{
::rtl::OUString columnName;
MQueryOp::cond_type op( MQueryOp::Is );
::rtl::OUString matchString;
if ( parseTree == NULL )
return;
if ( m_pSQLIterator->getParseTree() != NULL ) {
::rtl::Reference<OSQLColumns> xColumns = m_pSQLIterator->getParameters();
if(xColumns.is())
{
::rtl::OUString aColName, aParameterValue;
OSQLColumns::Vector::iterator aIter = xColumns->get().begin();
sal_Int32 i = 1;
for(;aIter != xColumns->get().end();++aIter)
{
(*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
OSL_TRACE("Prop Column Name : %s", OUtoCStr( aColName ) );
if ( m_aParameterRow.is() ) {
aParameterValue = (m_aParameterRow->get())[(sal_uInt16)i];
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Prop Value : %s", OUtoCStr( aParameterValue ) );
#endif
}
#if OSL_DEBUG_LEVEL > 0
else {
OSL_TRACE("Prop Value : Invalid ParameterRow!" );
}
#endif
i++;
}
}
}
if ( SQL_ISRULE(parseTree,where_clause) )
{
OSL_TRACE("analyseSQL : Got WHERE clause");
// Reset Parameter Counter
resetParameters();
analyseWhereClause( parseTree->getChild( 1 ), queryExpression );
}
else if ( parseTree->count() == 3 && // Handle ()'s
SQL_ISPUNCTUATION(parseTree->getChild(0),"(") &&
SQL_ISPUNCTUATION(parseTree->getChild(2),")"))
{
OSL_TRACE("analyseSQL : Got Punctuation ()");
MQueryExpression *subExpression = new MQueryExpression();
analyseWhereClause( parseTree->getChild( 1 ), *subExpression );
queryExpression.getExpressions().push_back( subExpression );
}
else if ((SQL_ISRULE(parseTree,search_condition) || (SQL_ISRULE(parseTree,boolean_term)))
&& parseTree->count() == 3) // Handle AND/OR
{
OSL_TRACE("analyseSQL : Got AND/OR clause");
// TODO - Need to take care or AND, for now match is always OR
analyseWhereClause( parseTree->getChild( 0 ), queryExpression );
analyseWhereClause( parseTree->getChild( 2 ), queryExpression );
if (SQL_ISTOKEN(parseTree->getChild(1),OR)) { // OR-Operator
queryExpression.setExpressionCondition( MQueryExpression::OR );
}
else if (SQL_ISTOKEN(parseTree->getChild(1),AND)) { // AND-Operator
queryExpression.setExpressionCondition( MQueryExpression::AND );
}
else {
OSL_FAIL("analyseSQL: Error in Parse Tree");
}
}
else if (SQL_ISRULE(parseTree,comparison_predicate))
{
OSL_ENSURE(parseTree->count() == 3, "Error parsing COMPARE predicate");
if (!(SQL_ISRULE(parseTree->getChild(0),column_ref) ||
parseTree->getChild(2)->getNodeType() == SQL_NODE_STRING ||
parseTree->getChild(2)->getNodeType() == SQL_NODE_INTNUM ||
parseTree->getChild(2)->getNodeType() == SQL_NODE_APPROXNUM ||
SQL_ISTOKEN(parseTree->getChild(2),TRUE) ||
SQL_ISTOKEN(parseTree->getChild(2),FALSE) ||
SQL_ISRULE(parseTree->getChild(2),parameter) ||
// odbc date
(SQL_ISRULE(parseTree->getChild(2),set_fct_spec) && SQL_ISPUNCTUATION(parseTree->getChild(2)->getChild(0),"{"))))
{
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
}
OSQLParseNode *pPrec = parseTree->getChild(1);
if (pPrec->getNodeType() == SQL_NODE_EQUAL)
op = MQueryOp::Is;
else if (pPrec->getNodeType() == SQL_NODE_NOTEQUAL)
op = MQueryOp::IsNot;
::rtl::OUString sTableRange;
if(SQL_ISRULE(parseTree->getChild(0),column_ref))
m_pSQLIterator->getColumnRange(parseTree->getChild(0),columnName,sTableRange);
else if(parseTree->getChild(0)->isToken())
columnName = parseTree->getChild(0)->getTokenValue();
if ( SQL_ISRULE(parseTree->getChild(2),parameter) ) {
parseParameter( parseTree->getChild(2), matchString );
}
else {
matchString = parseTree->getChild(2)->getTokenValue();
}
if ( columnName.compareToAscii("0") ==0 && op == MQueryOp::Is &&
matchString.compareToAscii("1") == 0 ) {
OSL_TRACE("Query always evaluates to FALSE");
m_bIsAlwaysFalseQuery = sal_True;
}
queryExpression.getExpressions().push_back( new MQueryExpressionString( columnName, op, matchString ));
}
else if (SQL_ISRULE(parseTree,like_predicate))
{
OSL_ENSURE(parseTree->count() == 2, "Error parsing LIKE predicate");
OSL_TRACE("analyseSQL : Got LIKE rule");
if ( !(SQL_ISRULE(parseTree->getChild(0), column_ref)) )
{
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_COLUMN, *this );
}
OSQLParseNode *pColumn;
OSQLParseNode *pAtom;
OSQLParseNode *pOptEscape;
const OSQLParseNode* pPart2 = parseTree->getChild(1);
pColumn = parseTree->getChild(0); // Match Item
pAtom = pPart2->getChild(static_cast<sal_uInt32>(pPart2->count()-2)); // Match String
pOptEscape = pPart2->getChild(static_cast<sal_uInt32>(pPart2->count()-1)); // Opt Escape Rule
(void)pOptEscape;
const bool bNot = SQL_ISTOKEN(pPart2->getChild(0), NOT);
if (!(pAtom->getNodeType() == SQL_NODE_STRING ||
pAtom->getNodeType() == SQL_NODE_NAME ||
SQL_ISRULE(pAtom,parameter) ||
( pAtom->getChild(0) && pAtom->getChild(0)->getNodeType() == SQL_NODE_NAME ) ||
( pAtom->getChild(0) && pAtom->getChild(0)->getNodeType() == SQL_NODE_STRING )
) )
{
OSL_TRACE("analyseSQL : pAtom->count() = %d", pAtom->count() );
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_STRING, *this );
}
const sal_Unicode WILDCARD = '%';
const sal_Unicode ALT_WILDCARD = '*';
const sal_Unicode MATCHCHAR = '_';
::rtl::OUString sTableRange;
if(SQL_ISRULE(pColumn,column_ref))
m_pSQLIterator->getColumnRange(pColumn,columnName,sTableRange);
OSL_TRACE("ColumnName = %s", OUtoCStr( columnName ) );
if ( SQL_ISRULE(pAtom,parameter) ) {
parseParameter( pAtom, matchString );
// Replace all '*' with '%' : UI Usually does this but not with
// Parameters for some reason.
matchString = matchString.replace( ALT_WILDCARD, WILDCARD );
}
else
{
matchString = pAtom->getTokenValue();
}
// Determine where '%' character is...
if ( matchString.equals( ::rtl::OUString::valueOf( WILDCARD ) ) )
{
// String containing only a '%' and nothing else
op = MQueryOp::Exists;
// Will be ignored for Exists case, but clear anyway.
matchString = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(""));
}
else if ( matchString.indexOf ( WILDCARD ) == -1 &&
matchString.indexOf ( MATCHCHAR ) == -1 )
{
// Simple string , eg. "to match"
if ( bNot )
op = MQueryOp::DoesNotContain;
else
op = MQueryOp::Contains;
}
else if ( matchString.indexOf ( WILDCARD ) == 0
&& matchString.lastIndexOf ( WILDCARD ) == matchString.getLength() -1
&& matchString.indexOf ( WILDCARD, 1 ) == matchString.lastIndexOf ( WILDCARD )
&& matchString.indexOf( MATCHCHAR ) == -1
)
{
// Relatively simple "%string%" - ie, contains...
// Cut '%' from front and rear
matchString = matchString.replaceAt( 0, 1, rtl::OUString() );
matchString = matchString.replaceAt( matchString.getLength() -1 , 1, rtl::OUString() );
if (bNot)
op = MQueryOp::DoesNotContain;
else
op = MQueryOp::Contains;
}
else if ( bNot )
{
// We currently can't handle a 'NOT LIKE' when there are '%' or
// '_' dispersed throughout
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_NOT_LIKE_TOO_COMPLEX, *this );
}
else
{
if ( (matchString.indexOf ( WILDCARD ) == matchString.lastIndexOf ( WILDCARD ))
&& matchString.indexOf( MATCHCHAR ) == -1
)
{
// One occurrence of '%' - no '_' matches...
if ( matchString.indexOf ( WILDCARD ) == 0 )
{
op = MQueryOp::EndsWith;
matchString = matchString.replaceAt( 0, 1, rtl::OUString());
}
else if ( matchString.indexOf ( WILDCARD ) == matchString.getLength() -1 )
{
op = MQueryOp::BeginsWith;
matchString = matchString.replaceAt( matchString.getLength() -1 , 1, rtl::OUString() );
}
else
{
sal_Int32 pos = matchString.indexOf ( WILDCARD );
matchString = matchString.replaceAt( pos, 1,::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".*")) );
op = MQueryOp::RegExp;
}
}
else
{
// Most Complex, need to use an RE
sal_Int32 pos = matchString.indexOf ( WILDCARD );
while ( (pos = matchString.indexOf ( WILDCARD )) != -1 )
{
matchString = matchString.replaceAt( pos, 1, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".*")) );
}
pos = matchString.indexOf ( MATCHCHAR );
while ( (pos = matchString.indexOf( MATCHCHAR )) != -1 )
{
matchString = matchString.replaceAt( pos, 1, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".")) );
}
op = MQueryOp::RegExp;
}
}
queryExpression.getExpressions().push_back( new MQueryExpressionString( columnName, op, matchString ));
}
else if (SQL_ISRULE(parseTree,test_for_null))
{
OSL_ENSURE(parseTree->count() == 2,"Error in ParseTree");
const OSQLParseNode* pPart2 = parseTree->getChild(1);
OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"Error in ParseTree");
if (!SQL_ISRULE(parseTree->getChild(0),column_ref))
{
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_IS_NULL_COLUMN, *this );
}
if (SQL_ISTOKEN(pPart2->getChild(1),NOT))
{
op = MQueryOp::Exists;
}
else
op = MQueryOp::DoesNotExist;
::rtl::OUString sTableRange;
m_pSQLIterator->getColumnRange(parseTree->getChild(0),columnName,sTableRange);
queryExpression.getExpressions().push_back( new MQueryExpressionString( columnName, op ));
}
else
{
OSL_TRACE( "Unexpected statement!!!" );
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
}
}
// -----------------------------------------------------------------------------
void OResultSet::fillRowData()
throw( ::com::sun::star::sdbc::SQLException )
{
OSL_ENSURE( m_pStatement, "Require a statement" );
MQueryExpression queryExpression;
OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
m_xColumns = m_pSQLIterator->getSelectColumns();
OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
OSQLColumns::Vector::const_iterator aIter = m_xColumns->get().begin();
const ::rtl::OUString sProprtyName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
::rtl::OUString sName;
m_aAttributeStrings.clear();
m_aAttributeStrings.reserve(m_xColumns->get().size());
for (sal_Int32 i = 1; aIter != m_xColumns->get().end();++aIter, i++)
{
(*aIter)->getPropertyValue(sProprtyName) >>= sName;
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Query Columns : (%d) %s", i, OUtoCStr(sName) );
#endif
m_aAttributeStrings.push_back( sName );
}
// Generate Match Conditions for Query
const OSQLParseNode* pParseTree = m_pSQLIterator->getWhereTree();
m_bIsAlwaysFalseQuery = sal_False;
if ( pParseTree != NULL )
{
// Extract required info
OSL_TRACE("\tHave a Where Clause");
analyseWhereClause( pParseTree, queryExpression );
}
#if 0
else
{
OSL_TRACE("\tDon't have a Where Clause");
MQueryExpression::ExprVector eVector;
// LDAP does not allow a query without restriction, so we add a dummy
// for PrimaryEmail
// For other types we stick to the old behaviour of using
// card:nsIAbCard.
OSL_ENSURE(m_pStatement, "Cannot determine Parent Statement");
::rtl::OUString aStr;
if (xConnection->isLDAP())
aStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PrimaryEmail"));
else
aStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("card:nsIAbCard"));
eVector.push_back( new MQueryExpressionString(aStr, MQueryOp::Exists) );
queryExpression.setExpressions( eVector );
}
#endif
// If the query is a 0=1 then set Row count to 0 and return
if ( m_bIsAlwaysFalseQuery )
{
m_bIsReadOnly = 1;
return;
}
m_aQueryHelper.setExpression( queryExpression );
rtl::OUString aStr( m_pTable->getName() );
m_aQueryHelper.setAddressbook( aStr );
sal_Int32 rv = m_aQueryHelper.executeQuery(xConnection);
if ( rv == -1 ) {
m_pStatement->getOwnConnection()->throwSQLException( STR_ERR_EXECUTING_QUERY, *this );
}
//determine whether the address book is readonly
determineReadOnly();
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE( "executeQuery returned %d", rv );
OSL_TRACE( "\tOUT OResultSet::fillRowData()" );
#endif
}
#if 0
// -----------------------------------------------------------------------------
void OResultSet::fillRowData()
throw( ::com::sun::star::sdbc::SQLException )
{
SAL_INFO("connectivity.mork", "=> OResultSet::fillRowData()" );
OSL_ENSURE( m_pStatement, "Require a statement" );
m_xColumns = m_pSQLIterator->getSelectColumns();
OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
sal_Int32 rv = m_aQueryHelper.executeQuery(xConnection);
if (rv == -1)
{
OSL_FAIL( "Error in executeQuery!" );
}
MQueryExpression queryExpression;
OSQLColumns::Vector::const_iterator aIter = m_xColumns->get().begin();
const ::rtl::OUString sProprtyName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
::rtl::OUString sName;
m_aAttributeStrings.clear();
m_aAttributeStrings.reserve(m_xColumns->get().size());
for (sal_Int32 i = 1; aIter != m_xColumns->get().end();++aIter, i++)
{
(*aIter)->getPropertyValue(sProprtyName) >>= sName;
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Query Columns : (%d) %s", i, OUtoCStr(sName) );
#endif
m_aAttributeStrings.push_back( sName );
}
// Generate Match Conditions for Query
const OSQLParseNode* pParseTree = m_pSQLIterator->getWhereTree();
// const OSQLParseNode* pParseTree = NULL;
m_bIsAlwaysFalseQuery = sal_False;
if ( pParseTree != NULL )
{
// Extract required info
OSL_TRACE("\tHave a Where Clause");
analyseWhereClause( pParseTree, queryExpression );
}
#if 0
else
{
OSL_TRACE("\tDon't have a Where Clause");
MQueryExpression::ExprVector eVector;
// LDAP does not allow a query without restriction, so we add a dummy
// for PrimaryEmail
// For other types we stick to the old behaviour of using
// card:nsIAbCard.
OSL_ENSURE(m_pStatement, "Cannot determine Parent Statement");
::rtl::OUString aStr;
if (xConnection->isLDAP())
aStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("PrimaryEmail"));
else
aStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("card:nsIAbCard"));
eVector.push_back( new MQueryExpressionString(aStr, MQueryOp::Exists) );
queryExpression.setExpressions( eVector );
}
#endif
// If the query is a 0=1 then set Row count to 0 and return
if ( m_bIsAlwaysFalseQuery )
{
m_bIsReadOnly = 1;
return;
}
m_aQueryHelper.setExpression( queryExpression );
rtl::OUString aStr( m_pTable->getName() );
m_aQueryHelper.setAddressbook( aStr );
sal_Int32 rv = m_aQueryHelper.executeQuery(xConnection);
if ( rv == -1 ) {
m_pStatement->getOwnConnection()->throwSQLException( STR_ERR_EXECUTING_QUERY, *this );
}
//determine whether the address book is readonly
determineReadOnly();
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE( "executeQuery returned %d", rv );
OSL_TRACE( "\tOUT OResultSet::fillRowData()" );
#endif
}
#endif
// -----------------------------------------------------------------------------
static sal_Bool matchRow( OValueRow& row1, OValueRow& row2 )
{
OValueVector::Vector::iterator row1Iter = row1->get().begin();
OValueVector::Vector::iterator row2Iter = row2->get().begin();
for ( ++row1Iter,++row2Iter; // the first column is the bookmark column
row1Iter != row1->get().end(); ++row1Iter,++row2Iter)
{
if ( row1Iter->isBound())
{
// Compare values, if at anytime there's a mismatch return false
if ( !( (*row1Iter) == (*row2Iter) ) )
return sal_False;
}
}
// If we get to here the rows match
return sal_True;
}
sal_Int32 OResultSet::getRowForCardNumber(sal_Int32 nCardNum)
{
OSL_TRACE("In/Out: OResultSet::getRowForCardNumber, nCardNum = %u", nCardNum );
if ( m_pKeySet.is() )
{
sal_Int32 nPos;
for(nPos=0;nPos < (sal_Int32)m_pKeySet->get().size();nPos++)
{
if (nCardNum == (m_pKeySet->get())[nPos])
{
OSL_TRACE("In/Out: OResultSet::getRowForCardNumber, return = %u", nPos+1 );
return nPos+1;
}
}
}
m_pStatement->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK, *this );
return 0;
}
#if 0
// -----------------------------------------------------------------------------
void SAL_CALL OResultSet::executeQuery() throw( ::com::sun::star::sdbc::SQLException,
::com::sun::star::uno::RuntimeException)
{
SAL_INFO("connectivity.mork", "=> OResultSet::executeQuery()" );
ResultSetEntryGuard aGuard( *this );
OSL_ENSURE( m_pTable, "Need a Table object");
if(!m_pTable)
{
const OSQLTables& xTabs = m_pSQLIterator->getTables();
if ((xTabs.begin() == xTabs.end()) || !xTabs.begin()->second.is()) {
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
}
m_pTable = static_cast< OTable* > ((xTabs.begin()->second).get());
}
m_nRowPos = 0;
fillRowData();
m_pKeySet = new OKeySet();
m_pSortIndex = new OSortIndex(SQL_ORDERBYKEY_DOUBLE, m_aOrderbyAscending);
m_pKeySet = m_pSortIndex->CreateKeySet();
OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
switch( m_pSQLIterator->getStatementType() )
{
case SQL_STATEMENT_SELECT:
{
if(m_bIsAlwaysFalseQuery) {
break;
}
else if(isCount())
{
OSL_FAIL( "STR_NO_COUNT_SUPPORT!" );
m_pStatement->getOwnConnection()->throwSQLException( STR_NO_COUNT_SUPPORT, *this );
}
else
{
sal_Bool bDistinct = sal_False;
OSQLParseNode *pDistinct = m_pParseTree->getChild(1);
if (pDistinct && pDistinct->getTokenID() == SQL_TOKEN_DISTINCT)
{
if(!IsSorted())
{
m_aOrderbyColumnNumber.push_back(m_aColMapping[1]);
m_aOrderbyAscending.push_back(SQL_DESC);
}
bDistinct = sal_True;
}
OSortIndex::TKeyTypeVector eKeyType(m_aOrderbyColumnNumber.size());
::std::vector<sal_Int32>::iterator aOrderByIter = m_aOrderbyColumnNumber.begin();
for ( ::std::vector<sal_Int16>::size_type i = 0; aOrderByIter != m_aOrderbyColumnNumber.end(); ++aOrderByIter,++i)
{
OSL_ENSURE((sal_Int32)m_aRow->get().size() > *aOrderByIter,"Invalid Index");
switch ((m_aRow->get().begin()+*aOrderByIter)->getTypeKind())
{
case DataType::CHAR:
case DataType::VARCHAR:
eKeyType[i] = SQL_ORDERBYKEY_STRING;
break;
case DataType::OTHER:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::INTEGER:
case DataType::DECIMAL:
case DataType::NUMERIC:
case DataType::REAL:
case DataType::DOUBLE:
case DataType::DATE:
case DataType::TIME:
case DataType::TIMESTAMP:
case DataType::BIT:
eKeyType[i] = SQL_ORDERBYKEY_DOUBLE;
break;
// Other types aren't implemented (so they are always FALSE)
default:
eKeyType[i] = SQL_ORDERBYKEY_NONE;
OSL_FAIL("MResultSet::executeQuery: Order By Data Type not implemented");
break;
}
}
if (IsSorted())
{
// Implement Sorting
// So that we can sort we need to wait until the executed
// query to the mozilla addressbooks has returned all
// values.
OSL_TRACE("Query is to be sorted");
if( ! m_aQueryHelper.queryComplete() )
if ( !m_aQueryHelper.waitForQueryComplete() )
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
OSL_ENSURE( m_aQueryHelper.queryComplete(), "Query not complete!!");
m_pSortIndex = new OSortIndex(eKeyType,m_aOrderbyAscending);
OSL_TRACE("OrderbyColumnNumber->size() = %d",m_aOrderbyColumnNumber.size());
#if OSL_DEBUG_LEVEL > 0
for ( ::std::vector<sal_Int32>::size_type i = 0; i < m_aColMapping.size(); i++ )
OSL_TRACE("Mapped: %d -> %d", i, m_aColMapping[i] );
#endif
for ( sal_Int32 nRow = 1; nRow <= m_aQueryHelper.getRowCount(); nRow++ ) {
OKeyValue* pKeyValue = OKeyValue::createKeyValue((nRow));
::std::vector<sal_Int32>::iterator aIter = m_aOrderbyColumnNumber.begin();
for (;aIter != m_aOrderbyColumnNumber.end(); ++aIter)
{
const ORowSetValue& value = getValue(nRow, *aIter);
OSL_TRACE( "Adding Value: (%d,%d) : %s", nRow, *aIter,OUtoCStr( value ));
pKeyValue->pushKey(new ORowSetValueDecorator(value));
}
m_pSortIndex->AddKeyValue( pKeyValue );
}
m_pKeySet = m_pSortIndex->CreateKeySet();
m_CurrentRowCount = static_cast<sal_Int32>(m_pKeySet->get().size());
#if OSL_DEBUG_LEVEL > 0
for( OKeySet::Vector::size_type i = 0; i < m_pKeySet->get().size(); i++ )
OSL_TRACE("Sorted: %d -> %d", i, (m_pKeySet->get())[i] );
#endif
m_pSortIndex = NULL;
beforeFirst(); // Go back to start
}
else //we always need m_pKeySet now
m_pKeySet = new OKeySet();
// Handle the DISTINCT case
if ( bDistinct && m_pKeySet.is() )
{
OValueRow aSearchRow = new OValueVector( m_aRow->get().size() );
for( OKeySet::Vector::size_type i = 0; i < m_pKeySet->get().size(); i++ )
{
fetchRow( (m_pKeySet->get())[i] ); // Fills m_aRow
if ( matchRow( m_aRow, aSearchRow ) )
{
(m_pKeySet->get())[i] = 0; // Marker for later to be removed
}
else
{
// They don't match, so it's not a duplicate.
// Use the current Row as the next one to match against
*aSearchRow = *m_aRow;
}
}
// Now remove any keys marked with a 0
m_pKeySet->get().erase(::std::remove_if(m_pKeySet->get().begin(),m_pKeySet->get().end()
,::std::bind2nd(::std::equal_to<sal_Int32>(),0))
,m_pKeySet->get().end());
}
}
} break;
case SQL_STATEMENT_UPDATE:
case SQL_STATEMENT_DELETE:
case SQL_STATEMENT_INSERT:
break;
default:
m_pStatement->getOwnConnection()->throwSQLException( STR_STMT_TYPE_NOT_SUPPORTED, *this );
break;
}
}
// -----------------------------------------------------------------------------
#endif
// -----------------------------------------------------------------------------
void SAL_CALL OResultSet::executeQuery() throw( ::com::sun::star::sdbc::SQLException,
::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_ENSURE( m_pTable, "Need a Table object");
if(!m_pTable)
{
const OSQLTables& xTabs = m_pSQLIterator->getTables();
if ((xTabs.begin() == xTabs.end()) || !xTabs.begin()->second.is())
m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
m_pTable = static_cast< OTable* > ((xTabs.begin()->second).get());
}
m_nRowPos = 0;
fillRowData();
OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
switch( m_pSQLIterator->getStatementType() )
{
case SQL_STATEMENT_SELECT:
{
if(m_bIsAlwaysFalseQuery) {
break;
}
else if(isCount())
{
m_pStatement->getOwnConnection()->throwSQLException( STR_NO_COUNT_SUPPORT, *this );
}
else
{
sal_Bool bDistinct = sal_False;
OSQLParseNode *pDistinct = m_pParseTree->getChild(1);
if (pDistinct && pDistinct->getTokenID() == SQL_TOKEN_DISTINCT)
{
if(!IsSorted())
{
m_aOrderbyColumnNumber.push_back(m_aColMapping[1]);
m_aOrderbyAscending.push_back(SQL_DESC);
}
bDistinct = sal_True;
}
OSortIndex::TKeyTypeVector eKeyType(m_aOrderbyColumnNumber.size());
::std::vector<sal_Int32>::iterator aOrderByIter = m_aOrderbyColumnNumber.begin();
for ( ::std::vector<sal_Int16>::size_type i = 0; aOrderByIter != m_aOrderbyColumnNumber.end(); ++aOrderByIter,++i)
{
OSL_ENSURE((sal_Int32)m_aRow->get().size() > *aOrderByIter,"Invalid Index");
switch ((m_aRow->get().begin()+*aOrderByIter)->getTypeKind())
{
case DataType::CHAR:
case DataType::VARCHAR:
eKeyType[i] = SQL_ORDERBYKEY_STRING;
break;
case DataType::OTHER:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::INTEGER:
case DataType::DECIMAL:
case DataType::NUMERIC:
case DataType::REAL:
case DataType::DOUBLE:
case DataType::DATE:
case DataType::TIME:
case DataType::TIMESTAMP:
case DataType::BIT:
eKeyType[i] = SQL_ORDERBYKEY_DOUBLE;
break;
// Other types aren't implemented (so they are always FALSE)
default:
eKeyType[i] = SQL_ORDERBYKEY_NONE;
OSL_FAIL("MResultSet::executeQuery: Order By Data Type not implemented");
break;
}
}
if (IsSorted())
{
// Implement Sorting
// So that we can sort we need to wait until the executed
// query to the mozilla addressbooks has returned all
// values.
OSL_TRACE("Query is to be sorted");
#if 0
if( ! m_aQueryHelper.queryComplete() )
if ( !m_aQueryHelper.waitForQueryComplete() )
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
#endif
OSL_ENSURE( m_aQueryHelper.queryComplete(), "Query not complete!!");
m_pSortIndex = new OSortIndex(eKeyType,m_aOrderbyAscending);
OSL_TRACE("OrderbyColumnNumber->size() = %d",m_aOrderbyColumnNumber.size());
#if OSL_DEBUG_LEVEL > 0
for ( ::std::vector<sal_Int32>::size_type i = 0; i < m_aColMapping.size(); i++ )
OSL_TRACE("Mapped: %d -> %d", i, m_aColMapping[i] );
#endif
for ( sal_Int32 nRow = 1; nRow <= m_aQueryHelper.getResultCount(); nRow++ ) {
OKeyValue* pKeyValue = OKeyValue::createKeyValue((nRow));
::std::vector<sal_Int32>::iterator aIter = m_aOrderbyColumnNumber.begin();
for (;aIter != m_aOrderbyColumnNumber.end(); ++aIter)
{
const ORowSetValue& value = getValue(nRow, *aIter);
OSL_TRACE( "Adding Value: (%d,%d) : %s", nRow, *aIter,OUtoCStr( value ));
pKeyValue->pushKey(new ORowSetValueDecorator(value));
}
m_pSortIndex->AddKeyValue( pKeyValue );
}
m_pKeySet = m_pSortIndex->CreateKeySet();
m_CurrentRowCount = static_cast<sal_Int32>(m_pKeySet->get().size());
#if OSL_DEBUG_LEVEL > 0
for( OKeySet::Vector::size_type i = 0; i < m_pKeySet->get().size(); i++ )
OSL_TRACE("Sorted: %d -> %d", i, (m_pKeySet->get())[i] );
#endif
m_pSortIndex = NULL;
beforeFirst(); // Go back to start
}
else //we always need m_pKeySet now
m_pKeySet = new OKeySet();
// Handle the DISTINCT case
if ( bDistinct && m_pKeySet.is() )
{
OValueRow aSearchRow = new OValueVector( m_aRow->get().size() );
for( OKeySet::Vector::size_type i = 0; i < m_pKeySet->get().size(); i++ )
{
fetchRow( (m_pKeySet->get())[i] ); // Fills m_aRow
if ( matchRow( m_aRow, aSearchRow ) )
{
(m_pKeySet->get())[i] = 0; // Marker for later to be removed
}
else
{
// They don't match, so it's not a duplicate.
// Use the current Row as the next one to match against
*aSearchRow = *m_aRow;
}
}
// Now remove any keys marked with a 0
m_pKeySet->get().erase(::std::remove_if(m_pKeySet->get().begin(),m_pKeySet->get().end()
,::std::bind2nd(::std::equal_to<sal_Int32>(),0))
,m_pKeySet->get().end());
}
}
} break;
case SQL_STATEMENT_UPDATE:
case SQL_STATEMENT_DELETE:
case SQL_STATEMENT_INSERT:
break;
default:
m_pStatement->getOwnConnection()->throwSQLException( STR_STMT_TYPE_NOT_SUPPORTED, *this );
break;
}
}
// -----------------------------------------------------------------------------
void OResultSet::setBoundedColumns(const OValueRow& _rRow,
const ::rtl::Reference<connectivity::OSQLColumns>& _rxColumns,
const Reference<XIndexAccess>& _xNames,
sal_Bool _bSetColumnMapping,
const Reference<XDatabaseMetaData>& _xMetaData,
::std::vector<sal_Int32>& _rColMapping)
{
::comphelper::UStringMixEqual aCase(_xMetaData->supportsMixedCaseQuotedIdentifiers());
Reference<XPropertySet> xTableColumn;
::rtl::OUString sTableColumnName, sSelectColumnRealName;
const ::rtl::OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
const ::rtl::OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
::std::vector< ::rtl::OUString> aColumnNames;
aColumnNames.reserve(_rxColumns->get().size());
OValueVector::Vector::iterator aRowIter = _rRow->get().begin()+1;
for (sal_Int32 i=0; // the first column is the bookmark column
aRowIter != _rRow->get().end();
++i, ++aRowIter
)
{
try
{
// get the table column and it's name
_xNames->getByIndex(i) >>= xTableColumn;
OSL_ENSURE(xTableColumn.is(), "OResultSet::setBoundedColumns: invalid table column!");
if (xTableColumn.is())
xTableColumn->getPropertyValue(sName) >>= sTableColumnName;
else
sTableColumnName = ::rtl::OUString();
// look if we have such a select column
// TODO: would like to have a O(log n) search here ...
sal_Int32 nColumnPos = 0;
for ( OSQLColumns::Vector::iterator aIter = _rxColumns->get().begin();
aIter != _rxColumns->get().end();
++aIter,++nColumnPos
)
{
if ( nColumnPos < (sal_Int32)aColumnNames.size() )
sSelectColumnRealName = aColumnNames[nColumnPos];
else
{
if((*aIter)->getPropertySetInfo()->hasPropertyByName(sRealName))
(*aIter)->getPropertyValue(sRealName) >>= sSelectColumnRealName;
else
(*aIter)->getPropertyValue(sName) >>= sSelectColumnRealName;
aColumnNames.push_back(sSelectColumnRealName);
}
if (aCase(sTableColumnName, sSelectColumnRealName))
{
if(_bSetColumnMapping)
{
sal_Int32 nSelectColumnPos = static_cast<sal_Int32>(aIter - _rxColumns->get().begin() + 1);
// the getXXX methods are 1-based ...
sal_Int32 nTableColumnPos = i + 1;
// get first table column is the bookmark column
// ...
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("Set Col Mapping: %d -> %d", nSelectColumnPos, nTableColumnPos );
#endif
_rColMapping[nSelectColumnPos] = nTableColumnPos;
}
aRowIter->setBound(sal_True);
aRowIter->setTypeKind(DataType::VARCHAR);
}
}
}
catch (Exception&)
{
OSL_FAIL("OResultSet::setBoundedColumns: caught an Exception!");
}
}
}
// -----------------------------------------------------------------------------
sal_Bool OResultSet::isCount() const
{
return (m_pParseTree &&
m_pParseTree->count() > 2 &&
SQL_ISRULE(m_pParseTree->getChild(2),scalar_exp_commalist) &&
SQL_ISRULE(m_pParseTree->getChild(2)->getChild(0),derived_column) &&
SQL_ISRULE(m_pParseTree->getChild(2)->getChild(0)->getChild(0),general_set_fct) &&
m_pParseTree->getChild(2)->getChild(0)->getChild(0)->count() == 4
);
}
// -----------------------------------------------------------------------------
//
// Check for valid row in m_aQuery
//
sal_Bool OResultSet::validRow( sal_uInt32 nRow)
{
sal_Int32 nNumberOfRecords = m_aQueryHelper.getResultCount();
while ( nRow > (sal_uInt32)nNumberOfRecords && !m_aQueryHelper.queryComplete() ) {
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("validRow: waiting...");
#endif
if (m_aQueryHelper.checkRowAvailable( nRow ) == sal_False)
{
OSL_TRACE("validRow(%u): return False", nRow);
return sal_False;
}
if ( m_aQueryHelper.hadError() )
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
nNumberOfRecords = m_aQueryHelper.getResultCount();
}
if (( nRow == 0 ) ||
( nRow > (sal_uInt32)nNumberOfRecords && m_aQueryHelper.queryComplete()) ){
OSL_TRACE("validRow(%u): return False", nRow);
return sal_False;
}
#if OSL_DEBUG_LEVEL > 0
OSL_TRACE("validRow(%u): return True", nRow);
#endif
return sal_True;
}
sal_Bool OResultSet::fillKeySet(sal_Int32 nMaxCardNumber)
{
impl_ensureKeySet();
if (m_CurrentRowCount < nMaxCardNumber)
{
sal_Int32 nKeyValue;
if ( (sal_Int32)m_pKeySet->get().capacity() < nMaxCardNumber )
m_pKeySet->get().reserve(nMaxCardNumber + 20 );
for (nKeyValue = m_CurrentRowCount+1; nKeyValue <= nMaxCardNumber; nKeyValue ++)
m_pKeySet->get().push_back( nKeyValue );
m_CurrentRowCount = nMaxCardNumber;
}
return sal_True;
}
sal_Int32 OResultSet::deletedCount()
{
impl_ensureKeySet();
return m_CurrentRowCount - static_cast<sal_Int32>(m_pKeySet->get().size());
}
// -----------------------------------------------------------------------------
sal_Bool OResultSet::seekRow( eRowPosition pos, sal_Int32 nOffset )
{
SAL_INFO("connectivity.mork", "=> OResultSet::seekRow()" );
ResultSetEntryGuard aGuard( *this );
if ( !m_pKeySet.is() )
m_pStatement->getOwnConnection()->throwSQLException( STR_ILLEGAL_MOVEMENT, *this );
sal_Int32 nNumberOfRecords = m_aQueryHelper.getResultCount();
sal_Int32 nRetrivedRows = currentRowCount();
sal_Int32 nCurPos = m_nRowPos;
OSL_TRACE("seekRow: nCurPos = %d", nCurPos );
switch( pos ) {
case NEXT_POS:
OSL_TRACE("seekRow: NEXT");
nCurPos++;
break;
case PRIOR_POS:
OSL_TRACE("seekRow: PRIOR");
if ( nCurPos > 0 )
nCurPos--;
break;
case FIRST_POS:
OSL_TRACE("seekRow: FIRST");
nCurPos = 1;
break;
case LAST_POS:
OSL_TRACE("seekRow: LAST");
nCurPos = nRetrivedRows;
break;
case ABSOLUTE_POS:
OSL_TRACE("seekRow: ABSOLUTE : %d", nOffset);
nCurPos = nOffset;
break;
case RELATIVE_POS:
OSL_TRACE("seekRow: RELATIVE : %d", nOffset);
nCurPos += sal_uInt32( nOffset );
break;
}
if ( nCurPos <= 0 ) {
m_nRowPos = 0;
OSL_TRACE("seekRow: return False, m_nRowPos = %u", m_nRowPos );
return sal_False;
}
sal_Int32 nCurCard = nCurPos;
if ( nCurPos < (sal_Int32)m_pKeySet->get().size() ) //The requested row is exist in m_pKeySet, so we just use it
{
nCurCard = (m_pKeySet->get())[nCurPos-1];
}
else //The requested row has not been retrived until now. We should get the right card for it.
nCurCard = nCurPos + deletedCount();
// davido: what is this loop for?
// it leads to infinite loop, once nCurCard is greater then nNumberOfRecords
#if 0
while ( nCurCard > nNumberOfRecords ) {
m_aQueryHelper.checkRowAvailable( nCurCard );
if ( m_aQueryHelper.hadError() )
{
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
nNumberOfRecords = m_aQueryHelper.getResultCount();
}
#endif
if ( nCurCard > nNumberOfRecords) {
fillKeySet(nNumberOfRecords);
m_nRowPos = static_cast<sal_uInt32>(m_pKeySet->get().size() + 1);
OSL_TRACE("seekRow: return False, m_nRowPos = %u", m_nRowPos );
return sal_False;
}
//Insert new retrived items for later use
fillKeySet(nNumberOfRecords);
m_nRowPos = (sal_uInt32)nCurPos;
OSL_TRACE("seekRow: return True, m_nRowPos = %u", m_nRowPos );
fetchCurrentRow();
return sal_True;
}
// -----------------------------------------------------------------------------
void OResultSet::setColumnMapping(const ::std::vector<sal_Int32>& _aColumnMapping)
{
m_aColMapping = _aColumnMapping;
#if OSL_DEBUG_LEVEL > 0
for ( sal_uInt32 i = 0; i < m_aColMapping.size(); i++ )
OSL_TRACE("Set Mapped: %d -> %d", i, m_aColMapping[i] );
#endif
}
// -----------------------------------------------------------------------------
::com::sun::star::uno::Any OResultSet::getBookmark( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
OSL_TRACE("getBookmark, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
if ( fetchCurrentRow() == sal_False ) {
m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
}
OSL_ENSURE((!m_aRow->isDeleted()),"getBookmark called for deleted row");
return makeAny((sal_Int32)(m_aRow->get())[0]);
}
sal_Bool OResultSet::moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("moveToBookmark, bookmark = %u", comphelper::getINT32(bookmark) );
sal_Int32 nCardNum = comphelper::getINT32(bookmark);
m_nRowPos = getRowForCardNumber(nCardNum);
fetchCurrentRow();
return sal_True;
}
sal_Bool OResultSet::moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("moveRelativeToBookmark, bookmark = %u rows= %u", comphelper::getINT32(bookmark),rows );
sal_Int32 nCardNum = comphelper::getINT32(bookmark);
m_nRowPos = getRowForCardNumber(nCardNum);
return seekRow(RELATIVE_POS,rows );
}
sal_Int32 OResultSet::compareBookmarks( const ::com::sun::star::uno::Any& lhs, const ::com::sun::star::uno::Any& rhs ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("compareBookmarks, m_nRowPos = %u", m_nRowPos );
sal_Int32 nFirst=0;
sal_Int32 nSecond=0;
sal_Int32 nResult=0;
if ( !( lhs >>= nFirst ) || !( rhs >>= nSecond ) ) {
m_pStatement->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK, *this );
}
if(nFirst < nSecond)
nResult = -1;
else if(nFirst > nSecond)
nResult = 1;
else
nResult = 0;
return nResult;
}
sal_Bool OResultSet::hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("hasOrderedBookmarks, m_nRowPos = %u", m_nRowPos );
return sal_True;
}
sal_Int32 OResultSet::hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("hashBookmark, m_nRowPos = %u", m_nRowPos );
return comphelper::getINT32(bookmark);
}
sal_Int32 OResultSet::getCurrentCardNumber()
{
if ( ( m_nRowPos == 0 ) || !m_pKeySet.is() )
return 0;
if (m_pKeySet->get().size() < m_nRowPos)
return 0;
return (m_pKeySet->get())[m_nRowPos-1];
}
void OResultSet::checkPendingUpdate() throw(SQLException, RuntimeException)
{
OSL_FAIL( "OResultSet::checkPendingUpdate() not implemented" );
/*
OSL_TRACE("checkPendingUpdate, m_nRowPos = %u", m_nRowPos );
const sal_Int32 nCurrentRow = getCurrentCardNumber();
if ((m_nNewRow && nCurrentRow != m_nNewRow)
|| ( m_nUpdatedRow && m_nUpdatedRow != nCurrentRow))
{
const ::rtl::OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
STR_COMMIT_ROW,
"$position$", ::rtl::OUString::valueOf(nCurrentRow)
) );
::dbtools::throwGenericSQLException(sError,*this);
}
*/
}
void OResultSet::updateValue(sal_Int32 columnIndex ,const ORowSetValue& x) throw(SQLException, RuntimeException)
{
OSL_TRACE("updateValue, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
if ( fetchCurrentRow() == sal_False ) {
m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
}
checkPendingUpdate();
checkIndex(columnIndex );
columnIndex = mapColumn(columnIndex);
(m_aRow->get())[columnIndex].setBound(sal_True);
(m_aRow->get())[columnIndex] = x;
m_nUpdatedRow = getCurrentCardNumber();
// m_RowStates = m_RowStates | RowStates_Updated;
}
// -----------------------------------------------------------------------------
void SAL_CALL OResultSet::updateNull( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
{
OSL_TRACE("updateNull, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
if ( fetchCurrentRow() == sal_False )
m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
checkPendingUpdate();
checkIndex(columnIndex );
columnIndex = mapColumn(columnIndex);
(m_aRow->get())[columnIndex].setBound(sal_True);
(m_aRow->get())[columnIndex].setNull();
m_nUpdatedRow = getCurrentCardNumber();
// m_RowStates = m_RowStates | RowStates_Updated;
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateLong( sal_Int32 /*columnIndex*/, sal_Int64 /*x*/ ) throw(SQLException, RuntimeException)
{
::dbtools::throwFeatureNotImplementedException( "XRowUpdate::updateLong", *this );
}
// -----------------------------------------------------------------------
void SAL_CALL OResultSet::updateFloat( sal_Int32 columnIndex, float x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException)
{
updateValue(columnIndex,x);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
if(!x.is())
::dbtools::throwFunctionSequenceException(*this);
Sequence<sal_Int8> aSeq;
x->readBytes(aSeq,length);
updateValue(columnIndex,aSeq);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
{
updateBinaryStream(columnIndex,x,length);
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateObject( sal_Int32 columnIndex, const Any& x ) throw(SQLException, RuntimeException)
{
if (!::dbtools::implUpdateObject(this, columnIndex, x))
{
const ::rtl::OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
STR_COLUMN_NOT_UPDATEABLE,
"$position$", ::rtl::OUString::valueOf(columnIndex)
) );
::dbtools::throwGenericSQLException(sError,*this);
} // if (!::dbtools::implUpdateObject(this, columnIndex, x))
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ ) throw(SQLException, RuntimeException)
{
if (!::dbtools::implUpdateObject(this, columnIndex, x))
{
const ::rtl::OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
STR_COLUMN_NOT_UPDATEABLE,
"$position$", ::rtl::OUString::valueOf(columnIndex)
) );
::dbtools::throwGenericSQLException(sError,*this);
}
}
// XResultSetUpdate
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::insertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("insertRow in, m_nRowPos = %u", m_nRowPos );
// m_RowStates = RowStates_Inserted;
updateRow();
m_nOldRowPos = 0;
m_nNewRow = 0;
//m_aQueryHelper.setRowStates(getCurrentCardNumber(),m_RowStates);
OSL_TRACE("insertRow out, m_nRowPos = %u", m_nRowPos );
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::updateRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
OSL_FAIL( "OResultSet::updateRow( ) not implemented" );
#if 0
OSL_TRACE("updateRow in, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
impl_ensureKeySet();
if (!m_nRowPos || m_pKeySet->get().size() < m_nRowPos )
{
m_pStatement->getOwnConnection()->throwSQLException( STR_INVALID_ROW_UPDATE, *this );
}
const sal_Int32 nCurrentCard = getCurrentCardNumber();
if (!pushCard(nCurrentCard))
{
m_RowStates = RowStates_Error;
m_pStatement->getOwnConnection()->throwSQLException( STR_ROW_CAN_NOT_SAVE, *this );
}
if (!m_aQueryHelper.commitRow(nCurrentCard))
{
m_RowStates = RowStates_Error;
m_nUpdatedRow = 0;
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
}
m_nUpdatedRow = 0;
fetchCurrentRow();
OSL_TRACE("updateRow out, m_nRowPos = %u", m_nRowPos );
#endif
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::deleteRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
OSL_FAIL( "OResultSet::deleteRow( ) not implemented" );
#if 0
OSL_TRACE("deleteRow, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
if (rowDeleted())
m_pStatement->getOwnConnection()->throwSQLException( STR_ROW_ALREADY_DELETED, *this );
const sal_Int32 nCurrentRow = getCurrentCardNumber();
//fetchRow(nCurrentRow);
if (!nCurrentRow)
m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
sal_Bool m_bRowDeleted = ( m_aQueryHelper.deleteRow( nCurrentRow ) > 0 );
if (!m_bRowDeleted)
m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
m_aQueryHelper.setRowStates(nCurrentRow,RowStates_Deleted);
m_pKeySet->get().erase(m_pKeySet->get().begin() + m_nRowPos -1);
m_RowStates = RowStates_Deleted;
OSL_TRACE("deleteRow out, m_nRowPos = %u", m_nRowPos );
#endif
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
OSL_FAIL( "OResultSet::cancelRowUpdates( ) not implemented" );
#if 0
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("cancelRowUpdates, m_nRowPos = %u", m_nRowPos );
if (fetchRow(getCurrentCardNumber(),sal_True)) //force fetch current row will cause we lose all change to the current row
m_pStatement->getOwnConnection()->throwSQLException( STR_CAN_NOT_CANCEL_ROW_UPDATE, *this );
#endif
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
OSL_FAIL( "OResultSet::moveToInsertRow( ) not implemented" );
#if 0
OSL_TRACE("moveToInsertRow in, m_nRowPos = %u", m_nRowPos );
ResultSetEntryGuard aGuard( *this );
m_nOldRowPos = m_nRowPos;
if (!m_nNewRow) //no new row now, insert one
{
checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
checkPendingUpdate();
if (rowUpdated())
{
if (m_nRowPos && !pushCard(getCurrentCardNumber()))
throw SQLException();
}
m_nNewRow = m_aQueryHelper.createNewCard();
if (!m_nNewRow)
m_pStatement->getOwnConnection()->throwSQLException( STR_CAN_NOT_CREATE_ROW, *this );
m_RowStates = RowStates_Normal;
fillKeySet(m_nNewRow);
}
else
m_nUpdatedRow = 0;
m_nRowPos = static_cast<sal_uInt32>(m_pKeySet->get().size());
fetchCurrentRow();
OSL_TRACE("moveToInsertRow out, m_nRowPos = %u", m_nRowPos );
#endif
}
// -------------------------------------------------------------------------
void SAL_CALL OResultSet::moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
ResultSetEntryGuard aGuard( *this );
OSL_TRACE("moveToCurrentRow, m_nRowPos = %u", m_nRowPos );
if (rowInserted())
{
m_nRowPos = m_nOldRowPos;
fetchCurrentRow();
}
}
sal_Bool OResultSet::determineReadOnly()
{
// OSL_FAIL( "OResultSet::determineReadOnly( ) not implemented" );
if (m_bIsReadOnly == -1)
{
m_bIsReadOnly = sal_True;
// OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
// m_bIsReadOnly = !m_aQueryHelper.isWritable(xConnection) || m_bIsAlwaysFalseQuery;
}
return m_bIsReadOnly != 0;
}
void OResultSet::setTable(OTable* _rTable)
{
OSL_TRACE("In : setTable");
m_pTable = _rTable;
m_pTable->acquire();
m_xTableColumns = m_pTable->getColumns();
if(m_xTableColumns.is())
m_aColumnNames = m_xTableColumns->getElementNames();
OSL_TRACE("Out : setTable");
}
void OResultSet::setOrderByColumns(const ::std::vector<sal_Int32>& _aColumnOrderBy)
{
m_aOrderbyColumnNumber = _aColumnOrderBy;
}
void OResultSet::setOrderByAscending(const ::std::vector<TAscendingOrder>& _aOrderbyAsc)
{
m_aOrderbyAscending = _aOrderbyAsc;
}
Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows( const Sequence< Any >& /*rows*/ ) throw(SQLException, RuntimeException)
{
::dbtools::throwFeatureNotImplementedException( "XDeleteRows::deleteRows", *this );
return Sequence< sal_Int32 >();
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */