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 .
20 #include <com/sun/star/sdbc/DataType.hpp>
21 #include <com/sun/star/beans/PropertyAttribute.hpp>
22 #include <comphelper/property.hxx>
23 #include <comphelper/sequence.hxx>
24 #include <cppuhelper/typeprovider.hxx>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <comphelper/extract.hxx>
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/sdbc/ResultSetType.hpp>
29 #include <com/sun/star/sdbc/FetchDirection.hpp>
30 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
31 #include <comphelper/types.hxx>
32 #include <connectivity/dbexception.hxx>
33 #include <connectivity/dbtools.hxx>
35 #include <TSortIndex.hxx>
36 #include <rtl/string.hxx>
39 #include "MResultSet.hxx"
40 #include "MResultSetMetaData.hxx"
41 #include "FDatabaseMetaDataResultSet.hxx"
43 #include "resource/mork_res.hrc"
44 #include "resource/common_res.hrc"
46 #if OSL_DEBUG_LEVEL > 0
47 # define OUtoCStr( x ) ( OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
48 #else /* OSL_DEBUG_LEVEL */
49 # define OUtoCStr( x ) ("dummy")
50 #endif /* OSL_DEBUG_LEVEL */
52 using namespace ::comphelper
;
53 using namespace connectivity
;
54 using namespace connectivity::mork
;
55 using namespace ::cppu
;
56 using namespace com::sun::star::uno
;
57 using namespace com::sun::star::lang
;
58 using namespace com::sun::star::beans
;
59 using namespace com::sun::star::sdbc
;
60 using namespace com::sun::star::container
;
61 using namespace com::sun::star::io
;
62 using namespace com::sun::star::util
;
65 // IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
66 OUString SAL_CALL
OResultSet::getImplementationName( ) throw ( RuntimeException
, std::exception
) \
68 return OUString("com.sun.star.sdbcx.mork.ResultSet");
71 Sequence
< OUString
> SAL_CALL
OResultSet::getSupportedServiceNames( ) throw( RuntimeException
, std::exception
)
73 ::com::sun::star::uno::Sequence
< OUString
> aSupported(2);
74 aSupported
[0] = "com.sun.star.sdbc.ResultSet";
75 aSupported
[1] = "com.sun.star.sdbcx.ResultSet";
79 sal_Bool SAL_CALL
OResultSet::supportsService( const OUString
& _rServiceName
) throw( RuntimeException
, std::exception
)
81 return cppu::supportsService(this, _rServiceName
);
85 OResultSet::OResultSet(OCommonStatement
* pStmt
, const ::boost::shared_ptr
< connectivity::OSQLParseTreeIterator
>& _pSQLIterator
)
86 : OResultSet_BASE(m_aMutex
)
87 ,OPropertySetHelper(OResultSet_BASE::rBHelper
)
95 ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE
)
96 ,m_nFetchDirection(FetchDirection::FORWARD
)
97 ,m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE
)
98 ,m_pSQLIterator( _pSQLIterator
)
99 ,m_pParseTree( _pSQLIterator
->getParseTree() )
100 ,m_aQueryHelper(pStmt
->getOwnConnection()->getColumnAlias())
102 ,m_CurrentRowCount(0)
104 ,m_bIsAlwaysFalseQuery(false)
112 //m_aQuery.setMaxNrOfReturns(pStmt->getOwnConnection()->getMaxResultRecords());
115 OResultSet::~OResultSet()
120 void OResultSet::disposing(void)
122 OPropertySetHelper::disposing();
124 ::osl::MutexGuard
aGuard(m_aMutex
);
126 m_xStatement
.clear();
130 m_xParamColumns
= NULL
;
139 Any SAL_CALL
OResultSet::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
141 Any aRet
= OPropertySetHelper::queryInterface(rType
);
143 aRet
= OResultSet_BASE::queryInterface(rType
);
147 Sequence
< Type
> SAL_CALL
OResultSet::getTypes( ) throw( RuntimeException
, std::exception
)
149 OTypeCollection
aTypes( ::getCppuType( (const Reference
< ::com::sun::star::beans::XMultiPropertySet
> *)0 ),
150 ::getCppuType( (const Reference
< ::com::sun::star::beans::XFastPropertySet
> *)0 ),
151 ::getCppuType( (const Reference
< ::com::sun::star::beans::XPropertySet
> *)0 ));
153 return ::comphelper::concatSequences(aTypes
.getTypes(),OResultSet_BASE::getTypes());
156 void OResultSet::methodEntry()
158 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
161 OSL_FAIL( "OResultSet::methodEntry: looks like we're disposed, but how is this possible?" );
162 throw DisposedException( OUString(), *this );
167 sal_Int32 SAL_CALL
OResultSet::findColumn( const OUString
& columnName
) throw(SQLException
, RuntimeException
, std::exception
)
169 ResultSetEntryGuard
aGuard( *this );
171 // find the first column with the name columnName
172 Reference
< XResultSetMetaData
> xMeta
= getMetaData();
173 sal_Int32 nLen
= xMeta
->getColumnCount();
177 if(xMeta
->isCaseSensitive(i
) ? columnName
== xMeta
->getColumnName(i
) :
178 columnName
.equalsIgnoreAsciiCase(xMeta
->getColumnName(i
)))
182 ::dbtools::throwInvalidColumnException( columnName
, *this );
184 return 0; // Never reached
187 Reference
< XInputStream
> SAL_CALL
OResultSet::getBinaryStream( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
192 Reference
< XInputStream
> SAL_CALL
OResultSet::getCharacterStream( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
198 sal_Bool SAL_CALL
OResultSet::getBoolean( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
200 ResultSetEntryGuard
aGuard( *this );
206 sal_Int8 SAL_CALL
OResultSet::getByte( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
208 ResultSetEntryGuard
aGuard( *this );
213 Sequence
< sal_Int8
> SAL_CALL
OResultSet::getBytes( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
215 ResultSetEntryGuard
aGuard( *this );
216 return Sequence
< sal_Int8
>();
220 Date SAL_CALL
OResultSet::getDate( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
222 ResultSetEntryGuard
aGuard( *this );
227 double SAL_CALL
OResultSet::getDouble( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
229 ResultSetEntryGuard
aGuard( *this );
234 float SAL_CALL
OResultSet::getFloat( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
236 ResultSetEntryGuard
aGuard( *this );
241 sal_Int32 SAL_CALL
OResultSet::getInt( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
243 ResultSetEntryGuard
aGuard( *this );
248 sal_Int32 SAL_CALL
OResultSet::getRow( ) throw(SQLException
, RuntimeException
, std::exception
)
250 ResultSetEntryGuard
aGuard( *this );
252 OSL_TRACE("In/Out: OResultSet::getRow, return = %u", m_nRowPos
);
257 sal_Int64 SAL_CALL
OResultSet::getLong( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
259 ResultSetEntryGuard
aGuard( *this );
264 Reference
< XResultSetMetaData
> SAL_CALL
OResultSet::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
266 ResultSetEntryGuard
aGuard( *this );
268 if(!m_xMetaData
.is())
269 m_xMetaData
= new OResultSetMetaData(
270 m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
,m_pTable
,determineReadOnly());
274 Reference
< XArray
> SAL_CALL
OResultSet::getArray( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
281 Reference
< XClob
> SAL_CALL
OResultSet::getClob( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
286 Reference
< XBlob
> SAL_CALL
OResultSet::getBlob( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
292 Reference
< XRef
> SAL_CALL
OResultSet::getRef( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
298 Any SAL_CALL
OResultSet::getObject( sal_Int32
/*columnIndex*/, const Reference
< ::com::sun::star::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
, std::exception
)
304 sal_Int16 SAL_CALL
OResultSet::getShort( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
310 void OResultSet::checkIndex(sal_Int32 columnIndex
) throw(::com::sun::star::sdbc::SQLException
)
312 if(columnIndex
<= 0 || columnIndex
> (sal_Int32
)m_xColumns
->get().size())
313 ::dbtools::throwInvalidIndexException(*this);
316 sal_uInt32
OResultSet::currentRowCount()
318 if ( m_bIsAlwaysFalseQuery
)
320 //return 0;//m_aQuery.getRealRowCount() - deletedCount();
321 // new implementation
322 return m_aQueryHelper
.getResultCount();
327 bool OResultSet::fetchCurrentRow( ) throw(SQLException
, RuntimeException
)
329 OSL_TRACE("fetchCurrentRow, m_nRowPos = %u", m_nRowPos
);
330 return fetchRow(getCurrentCardNumber());
334 bool OResultSet::pushCard(sal_uInt32
/*cardNumber*/) throw(SQLException
, RuntimeException
)
340 // Check whether we are storing the updated row
341 if ( (m_aRow->get())[0].isNull() || (sal_Int32)(m_aRow->get())[0] != (sal_Int32)cardNumber )
344 sal_Int32 nCount = m_aColumnNames.getLength();
345 m_aQuery.setRowStates(cardNumber,m_RowStates);
346 for( sal_Int32 i = 1; i <= nCount; i++ )
348 if ( (m_aRow->get())[i].isBound() )
351 // Everything in the addressbook is a string!
353 if ( !m_aQuery.setRowValue( (m_aRow->get())[i], cardNumber, m_aColumnNames[i-1], DataType::VARCHAR ))
355 m_pStatement->getOwnConnection()->throwSQLException( m_aQuery.getError(), *this );
363 bool OResultSet::fetchRow(sal_Int32 cardNumber
,bool bForceReload
) throw(SQLException
, RuntimeException
)
365 OSL_TRACE("fetchRow, cardNumber = %u", cardNumber
);
368 // Check whether we've already fetched the row...
369 if ( !(m_aRow
->get())[0].isNull() && (sal_Int32
)(m_aRow
->get())[0] == (sal_Int32
)cardNumber
)
371 //Check whether the old row has been changed
372 if (cardNumber
== m_nUpdatedRow
)
374 //write back the changes first
375 if (!pushCard(cardNumber
)) //error write back the changes
376 throw SQLException();
380 // m_aQuery.resyncRow(cardNumber);
382 if ( validRow( cardNumber
) == false )
385 (m_aRow
->get())[0] = (sal_Int32
)cardNumber
;
386 sal_Int32 nCount
= m_aColumnNames
.getLength();
387 //m_RowStates = m_aQuery.getRowStates(cardNumber);
388 for( sal_Int32 i
= 1; i
<= nCount
; i
++ )
390 if ( (m_aRow
->get())[i
].isBound() )
393 // Everything in the addressbook is a string!
395 if ( !m_aQueryHelper
.getRowValue( (m_aRow
->get())[i
], cardNumber
, m_aColumnNames
[i
-1], DataType::VARCHAR
))
397 m_pStatement
->getOwnConnection()->throwSQLException( m_aQueryHelper
.getError(), *this );
406 const ORowSetValue
& OResultSet::getValue(sal_Int32 cardNumber
, sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
408 if ( fetchRow( cardNumber
) == false )
410 OSL_FAIL("fetchRow() returned False" );
412 return *ODatabaseMetaDataResultSet::getEmptyValue();
415 m_bWasNull
= (m_aRow
->get())[columnIndex
].isNull();
416 return (m_aRow
->get())[columnIndex
];
422 OUString SAL_CALL
OResultSet::getString( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
424 ResultSetEntryGuard
aGuard( *this );
426 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
427 OSL_ENSURE(columnIndex
<= (sal_Int32
)m_xColumns
->get().size(), "Trying to access invalid columns number");
428 checkIndex( columnIndex
);
430 // If this query was sorted then we should have a valid KeySet, so use it
431 return getValue(getCurrentCardNumber(), mapColumn( columnIndex
) );
436 Time SAL_CALL
OResultSet::getTime( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
438 ResultSetEntryGuard
aGuard( *this );
444 DateTime SAL_CALL
OResultSet::getTimestamp( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
446 ResultSetEntryGuard
aGuard( *this );
451 sal_Bool SAL_CALL
OResultSet::isBeforeFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
453 ResultSetEntryGuard
aGuard( *this );
455 // here you have to implement your movements
456 // return true means there is no data
457 OSL_TRACE("In/Out: OResultSet::isBeforeFirst" );
458 return( m_nRowPos
< 1 );
461 sal_Bool SAL_CALL
OResultSet::isAfterLast( ) throw(SQLException
, RuntimeException
, std::exception
)
463 SAL_WARN("connectivity.mork", "OResultSet::isAfterLast() NOT IMPLEMENTED!");
464 ResultSetEntryGuard
aGuard( *this );
466 OSL_TRACE("In/Out: OResultSet::isAfterLast" );
468 return m_nRowPos
> currentRowCount() && m_aQueryHelper
.queryComplete();
471 sal_Bool SAL_CALL
OResultSet::isFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
473 ResultSetEntryGuard
aGuard( *this );
475 OSL_TRACE("In/Out: OResultSet::isFirst" );
476 return m_nRowPos
== 1;
479 sal_Bool SAL_CALL
OResultSet::isLast( ) throw(SQLException
, RuntimeException
, std::exception
)
481 SAL_WARN("connectivity.mork", "OResultSet::isLast() NOT IMPLEMENTED!");
482 ResultSetEntryGuard
aGuard( *this );
484 OSL_TRACE("In/Out: OResultSet::isLast" );
486 return m_nRowPos
== currentRowCount() && m_aQueryHelper
.queryComplete();
489 void SAL_CALL
OResultSet::beforeFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
491 ResultSetEntryGuard
aGuard( *this );
493 // move before the first row so that isBeforeFirst returns false
494 OSL_TRACE("In/Out: OResultSet::beforeFirst" );
499 void SAL_CALL
OResultSet::afterLast( ) throw(SQLException
, RuntimeException
, std::exception
)
501 ResultSetEntryGuard
aGuard( *this );
502 OSL_TRACE("In/Out: OResultSet::afterLast" );
509 void SAL_CALL
OResultSet::close() throw(SQLException
, RuntimeException
, std::exception
)
511 OSL_TRACE("In/Out: OResultSet::close" );
516 sal_Bool SAL_CALL
OResultSet::first( ) throw(SQLException
, RuntimeException
, std::exception
)
518 OSL_TRACE("In/Out: OResultSet::first" );
519 return seekRow( FIRST_POS
);
523 sal_Bool SAL_CALL
OResultSet::last( ) throw(SQLException
, RuntimeException
, std::exception
)
525 OSL_TRACE("In/Out: OResultSet::last" );
526 return seekRow( LAST_POS
);
529 sal_Bool SAL_CALL
OResultSet::absolute( sal_Int32 row
) throw(SQLException
, RuntimeException
, std::exception
)
531 OSL_TRACE("In/Out: OResultSet::absolute" );
532 return seekRow( ABSOLUTE_POS
, row
);
535 sal_Bool SAL_CALL
OResultSet::relative( sal_Int32 row
) throw(SQLException
, RuntimeException
, std::exception
)
537 OSL_TRACE("In/Out: OResultSet::relative" );
538 return seekRow( RELATIVE_POS
, row
);
541 sal_Bool SAL_CALL
OResultSet::previous( ) throw(SQLException
, RuntimeException
, std::exception
)
543 ResultSetEntryGuard
aGuard( *this );
544 OSL_TRACE("In/Out: OResultSet::previous" );
545 return seekRow( PRIOR_POS
);
548 Reference
< XInterface
> SAL_CALL
OResultSet::getStatement( ) throw(SQLException
, RuntimeException
, std::exception
)
550 ResultSetEntryGuard
aGuard( *this );
552 OSL_TRACE("In/Out: OResultSet::getStatement" );
557 sal_Bool SAL_CALL
OResultSet::rowDeleted( ) throw(SQLException
, RuntimeException
, std::exception
)
559 SAL_WARN("connectivity.mork", "OResultSet::rowDeleted() NOT IMPLEMENTED!");
560 ResultSetEntryGuard
aGuard( *this );
561 OSL_TRACE("In/Out: OResultSet::rowDeleted, m_RowStates=%u",m_RowStates
);
562 return sal_True
;//return ((m_RowStates & RowStates_Deleted) == RowStates_Deleted) ;
565 sal_Bool SAL_CALL
OResultSet::rowInserted( ) throw(SQLException
, RuntimeException
, std::exception
)
567 SAL_WARN("connectivity.mork", "OResultSet::rowInserted() NOT IMPLEMENTED!");
568 ResultSetEntryGuard
aGuard( *this );
569 OSL_TRACE("In/Out: OResultSet::rowInserted,m_RowStates=%u",m_RowStates
);
570 return sal_True
;//return ((m_RowStates & RowStates_Inserted) == RowStates_Inserted);
573 sal_Bool SAL_CALL
OResultSet::rowUpdated( ) throw(SQLException
, RuntimeException
, std::exception
)
575 SAL_WARN("connectivity.mork", "OResultSet::rowUpdated() NOT IMPLEMENTED!");
576 ResultSetEntryGuard
aGuard( *this );
577 OSL_TRACE("In/Out: OResultSet::rowUpdated,m_RowStates=%u",m_RowStates
);
578 return sal_True
;// return ((m_RowStates & RowStates_Updated) == RowStates_Updated) ;
582 sal_Bool SAL_CALL
OResultSet::next( ) throw(SQLException
, RuntimeException
, std::exception
)
584 return seekRow( NEXT_POS
);
588 sal_Bool SAL_CALL
OResultSet::wasNull( ) throw(SQLException
, RuntimeException
, std::exception
)
590 ResultSetEntryGuard
aGuard( *this );
596 void SAL_CALL
OResultSet::cancel( ) throw(RuntimeException
, std::exception
)
598 ResultSetEntryGuard
aGuard( *this );
599 OSL_TRACE("In/Out: OResultSet::cancel" );
603 void SAL_CALL
OResultSet::clearWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
605 OSL_TRACE("In/Out: OResultSet::clearWarnings" );
608 Any SAL_CALL
OResultSet::getWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
610 OSL_TRACE("In/Out: OResultSet::getWarnings" );
614 void SAL_CALL
OResultSet::refreshRow( ) throw(SQLException
, RuntimeException
, std::exception
)
616 OSL_TRACE("In/Out: OResultSet::refreshRow" );
617 if (fetchRow(getCurrentCardNumber(),true)) {
618 //force fetch current row will cause we lose all change to the current row
619 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_REFRESH_ROW
, *this );
623 IPropertyArrayHelper
* OResultSet::createArrayHelper( ) const
625 Sequence
< Property
> aProps(5);
626 Property
* pProperties
= aProps
.getArray();
628 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION
),
629 PROPERTY_ID_FETCHDIRECTION
, cppu::UnoType
<sal_Int32
>::get(), 0);
631 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE
),
632 PROPERTY_ID_FETCHSIZE
, cppu::UnoType
<sal_Int32
>::get(), 0);
634 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE
),
635 PROPERTY_ID_ISBOOKMARKABLE
, ::getBooleanCppuType(), PropertyAttribute::READONLY
);
637 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY
),
638 PROPERTY_ID_RESULTSETCONCURRENCY
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
640 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE
),
641 PROPERTY_ID_RESULTSETTYPE
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
643 return new OPropertyArrayHelper(aProps
);
646 IPropertyArrayHelper
& OResultSet::getInfoHelper()
648 return *const_cast<OResultSet
*>(this)->getArrayHelper();
651 sal_Bool
OResultSet::convertFastPropertyValue(
652 Any
& /*rConvertedValue*/,
655 const Any
& /*rValue*/ )
656 throw (::com::sun::star::lang::IllegalArgumentException
)
658 OSL_FAIL( "OResultSet::convertFastPropertyValue: not implemented!" );
661 case PROPERTY_ID_ISBOOKMARKABLE
:
662 case PROPERTY_ID_RESULTSETCONCURRENCY
:
663 case PROPERTY_ID_RESULTSETTYPE
:
664 throw ::com::sun::star::lang::IllegalArgumentException();
665 case PROPERTY_ID_FETCHDIRECTION
:
666 case PROPERTY_ID_FETCHSIZE
:
673 void OResultSet::setFastPropertyValue_NoBroadcast(
675 const Any
& /*rValue*/
677 throw (Exception
, std::exception
)
679 OSL_FAIL( "OResultSet::setFastPropertyValue_NoBroadcast: not implemented!" );
682 case PROPERTY_ID_ISBOOKMARKABLE
:
683 case PROPERTY_ID_RESULTSETCONCURRENCY
:
684 case PROPERTY_ID_RESULTSETTYPE
:
686 case PROPERTY_ID_FETCHDIRECTION
:
688 case PROPERTY_ID_FETCHSIZE
:
695 void OResultSet::getFastPropertyValue(
702 case PROPERTY_ID_RESULTSETCONCURRENCY
:
703 rValue
<<= (sal_Int32
)m_nResultSetConcurrency
;
705 case PROPERTY_ID_RESULTSETTYPE
:
706 rValue
<<= m_nResultSetType
;
708 case PROPERTY_ID_FETCHDIRECTION
:
709 rValue
<<= m_nFetchDirection
;
711 case PROPERTY_ID_FETCHSIZE
:
712 rValue
<<= m_nFetchSize
;
714 case PROPERTY_ID_ISBOOKMARKABLE
:
715 const_cast< OResultSet
* >( this )->determineReadOnly();
716 rValue
<<= !m_bIsReadOnly
;
721 void SAL_CALL
OResultSet::acquire() throw()
723 OResultSet_BASE::acquire();
726 void SAL_CALL
OResultSet::release() throw()
728 OResultSet_BASE::release();
731 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
OResultSet::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
733 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
737 void OResultSet::parseParameter( const OSQLParseNode
* pNode
, OUString
& rMatchString
)
739 OSL_ENSURE(pNode
->count() > 0,"Error parsing parameter in Parse Tree");
740 OSQLParseNode
*pMark
= pNode
->getChild(0);
742 // Initialize to empty string
745 OUString aParameterName
;
746 if (SQL_ISPUNCTUATION(pMark
,"?")) {
747 aParameterName
= "?";
749 else if (SQL_ISPUNCTUATION(pMark
,":")) {
750 aParameterName
= pNode
->getChild(1)->getTokenValue();
752 // XXX - Now we know name, what's value????
754 OSL_TRACE("Parameter name [%d]: %s", m_nParamIndex
,OUtoCStr(aParameterName
) );
756 if ( m_aParameterRow
.is() ) {
757 OSL_ENSURE( m_nParamIndex
< (sal_Int32
)m_aParameterRow
->get().size() + 1, "More parameters than values found" );
758 rMatchString
= (m_aParameterRow
->get())[(sal_uInt16
)m_nParamIndex
];
759 #if OSL_DEBUG_LEVEL > 0
760 OSL_TRACE("Prop Value : %s", OUtoCStr( rMatchString
) );
763 #if OSL_DEBUG_LEVEL > 0
765 OSL_TRACE("Prop Value : Invalid ParameterRow!" );
771 #define ALT_WILDCARD "*"
772 static const sal_Unicode MATCHCHAR
= '_';
774 void OResultSet::analyseWhereClause( const OSQLParseNode
* parseTree
,
775 MQueryExpression
&queryExpression
)
778 MQueryOp::cond_type
op( MQueryOp::Is
);
779 OUString matchString
;
781 if ( parseTree
== NULL
)
784 if ( m_pSQLIterator
->getParseTree() != NULL
) {
785 ::rtl::Reference
<OSQLColumns
> xColumns
= m_pSQLIterator
->getParameters();
788 OUString aColName
, aParameterValue
;
789 OSQLColumns::Vector::iterator aIter
= xColumns
->get().begin();
791 for(;aIter
!= xColumns
->get().end();++aIter
)
793 (*aIter
)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
)) >>= aColName
;
794 OSL_TRACE("Prop Column Name : %s", OUtoCStr( aColName
) );
795 if ( m_aParameterRow
.is() ) {
796 aParameterValue
= (m_aParameterRow
->get())[(sal_uInt16
)i
];
797 #if OSL_DEBUG_LEVEL > 0
798 OSL_TRACE("Prop Value : %s", OUtoCStr( aParameterValue
) );
801 #if OSL_DEBUG_LEVEL > 0
803 OSL_TRACE("Prop Value : Invalid ParameterRow!" );
812 if ( SQL_ISRULE(parseTree
,where_clause
) )
814 OSL_TRACE("analyseSQL : Got WHERE clause");
815 // Reset Parameter Counter
817 analyseWhereClause( parseTree
->getChild( 1 ), queryExpression
);
819 else if ( parseTree
->count() == 3 && // Handle ()'s
820 SQL_ISPUNCTUATION(parseTree
->getChild(0),"(") &&
821 SQL_ISPUNCTUATION(parseTree
->getChild(2),")"))
824 OSL_TRACE("analyseSQL : Got Punctuation ()");
825 MQueryExpression
*subExpression
= new MQueryExpression();
826 analyseWhereClause( parseTree
->getChild( 1 ), *subExpression
);
827 queryExpression
.getExpressions().push_back( subExpression
);
829 else if ((SQL_ISRULE(parseTree
,search_condition
) || (SQL_ISRULE(parseTree
,boolean_term
)))
830 && parseTree
->count() == 3) // Handle AND/OR
833 OSL_TRACE("analyseSQL : Got AND/OR clause");
835 // TODO - Need to take care or AND, for now match is always OR
836 analyseWhereClause( parseTree
->getChild( 0 ), queryExpression
);
837 analyseWhereClause( parseTree
->getChild( 2 ), queryExpression
);
839 if (SQL_ISTOKEN(parseTree
->getChild(1),OR
)) { // OR-Operator
840 queryExpression
.setExpressionCondition( MQueryExpression::OR
);
842 else if (SQL_ISTOKEN(parseTree
->getChild(1),AND
)) { // AND-Operator
843 queryExpression
.setExpressionCondition( MQueryExpression::AND
);
846 OSL_FAIL("analyseSQL: Error in Parse Tree");
849 else if (SQL_ISRULE(parseTree
,comparison_predicate
))
851 OSL_ENSURE(parseTree
->count() == 3, "Error parsing COMPARE predicate");
852 if (!(SQL_ISRULE(parseTree
->getChild(0),column_ref
) ||
853 parseTree
->getChild(2)->getNodeType() == SQL_NODE_STRING
||
854 parseTree
->getChild(2)->getNodeType() == SQL_NODE_INTNUM
||
855 parseTree
->getChild(2)->getNodeType() == SQL_NODE_APPROXNUM
||
856 SQL_ISTOKEN(parseTree
->getChild(2),TRUE
) ||
857 SQL_ISTOKEN(parseTree
->getChild(2),FALSE
) ||
858 SQL_ISRULE(parseTree
->getChild(2),parameter
) ||
860 (SQL_ISRULE(parseTree
->getChild(2),set_fct_spec
) && SQL_ISPUNCTUATION(parseTree
->getChild(2)->getChild(0),"{"))))
862 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
865 OSQLParseNode
*pPrec
= parseTree
->getChild(1);
866 if (pPrec
->getNodeType() == SQL_NODE_EQUAL
)
868 else if (pPrec
->getNodeType() == SQL_NODE_NOTEQUAL
)
869 op
= MQueryOp::IsNot
;
871 OUString sTableRange
;
872 if(SQL_ISRULE(parseTree
->getChild(0),column_ref
))
873 m_pSQLIterator
->getColumnRange(parseTree
->getChild(0),columnName
,sTableRange
);
874 else if(parseTree
->getChild(0)->isToken())
875 columnName
= parseTree
->getChild(0)->getTokenValue();
877 if ( SQL_ISRULE(parseTree
->getChild(2),parameter
) ) {
878 parseParameter( parseTree
->getChild(2), matchString
);
881 matchString
= parseTree
->getChild(2)->getTokenValue();
884 if ( columnName
.equalsAscii("0") && op
== MQueryOp::Is
&&
885 matchString
.equalsAscii("1") ) {
886 OSL_TRACE("Query always evaluates to FALSE");
887 m_bIsAlwaysFalseQuery
= true;
889 queryExpression
.getExpressions().push_back( new MQueryExpressionString( columnName
, op
, matchString
));
891 else if (SQL_ISRULE(parseTree
,like_predicate
))
893 OSL_ENSURE(parseTree
->count() == 2, "Error parsing LIKE predicate");
895 OSL_TRACE("analyseSQL : Got LIKE rule");
897 if ( !(SQL_ISRULE(parseTree
->getChild(0), column_ref
)) )
899 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_COLUMN
, *this );
903 OSQLParseNode
*pColumn
;
904 OSQLParseNode
*pAtom
;
905 OSQLParseNode
*pOptEscape
;
906 const OSQLParseNode
* pPart2
= parseTree
->getChild(1);
907 pColumn
= parseTree
->getChild(0); // Match Item
908 pAtom
= pPart2
->getChild(static_cast<sal_uInt32
>(pPart2
->count()-2)); // Match String
909 pOptEscape
= pPart2
->getChild(static_cast<sal_uInt32
>(pPart2
->count()-1)); // Opt Escape Rule
911 const bool bNot
= SQL_ISTOKEN(pPart2
->getChild(0), NOT
);
913 if (!(pAtom
->getNodeType() == SQL_NODE_STRING
||
914 pAtom
->getNodeType() == SQL_NODE_NAME
||
915 SQL_ISRULE(pAtom
,parameter
) ||
916 ( pAtom
->getChild(0) && pAtom
->getChild(0)->getNodeType() == SQL_NODE_NAME
) ||
917 ( pAtom
->getChild(0) && pAtom
->getChild(0)->getNodeType() == SQL_NODE_STRING
)
920 OSL_TRACE("analyseSQL : pAtom->count() = %zu", pAtom
->count() );
922 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_STRING
, *this );
925 OUString sTableRange
;
926 if(SQL_ISRULE(pColumn
,column_ref
))
927 m_pSQLIterator
->getColumnRange(pColumn
,columnName
,sTableRange
);
929 OSL_TRACE("ColumnName = %s", OUtoCStr( columnName
) );
931 if ( SQL_ISRULE(pAtom
,parameter
) ) {
932 parseParameter( pAtom
, matchString
);
933 // Replace all '*' with '%' : UI Usually does this but not with
934 // Parameters for some reason.
935 matchString
= matchString
.replaceAll( ALT_WILDCARD
, WILDCARD
);
939 matchString
= pAtom
->getTokenValue();
942 // Determine where '%' character is...
944 if ( matchString
== WILDCARD
)
946 // String containing only a '%' and nothing else
947 op
= MQueryOp::Exists
;
948 // Will be ignored for Exists case, but clear anyway.
951 else if ( matchString
.indexOf ( WILDCARD
) == -1 &&
952 matchString
.indexOf ( MATCHCHAR
) == -1 )
954 // Simple string , eg. "to match"
956 op
= MQueryOp::DoesNotContain
;
958 op
= MQueryOp::Contains
;
960 else if ( matchString
.startsWith( WILDCARD
)
961 && matchString
.endsWith( WILDCARD
)
962 && matchString
.indexOf ( WILDCARD
, 1 ) == matchString
.lastIndexOf ( WILDCARD
)
963 && matchString
.indexOf( MATCHCHAR
) == -1
966 // Relatively simple "%string%" - ie, contains...
967 // Cut '%' from front and rear
968 matchString
= matchString
.replaceAt( 0, 1, OUString() );
969 matchString
= matchString
.replaceAt( matchString
.getLength() -1 , 1, OUString() );
972 op
= MQueryOp::DoesNotContain
;
974 op
= MQueryOp::Contains
;
978 // We currently can't handle a 'NOT LIKE' when there are '%' or
979 // '_' dispersed throughout
980 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_NOT_LIKE_TOO_COMPLEX
, *this );
984 if ( (matchString
.indexOf ( WILDCARD
) == matchString
.lastIndexOf ( WILDCARD
))
985 && matchString
.indexOf( MATCHCHAR
) == -1
988 // One occurrence of '%' - no '_' matches...
989 if ( matchString
.startsWith( WILDCARD
) )
991 op
= MQueryOp::EndsWith
;
992 matchString
= matchString
.replaceAt( 0, 1, OUString());
994 else if ( matchString
.indexOf ( WILDCARD
) == matchString
.getLength() -1 )
996 op
= MQueryOp::BeginsWith
;
997 matchString
= matchString
.replaceAt( matchString
.getLength() -1 , 1, OUString() );
1001 sal_Int32 pos
= matchString
.indexOf ( WILDCARD
);
1002 matchString
= matchString
.replaceAt( pos
, 1, ".*" );
1003 op
= MQueryOp::RegExp
;
1009 // Most Complex, need to use an RE
1011 while ( (pos
= matchString
.indexOf ( WILDCARD
)) != -1 )
1013 matchString
= matchString
.replaceAt( pos
, 1, OUString(".*") );
1016 while ( (pos
= matchString
.indexOf( MATCHCHAR
)) != -1 )
1018 matchString
= matchString
.replaceAt( pos
, 1, OUString(".") );
1021 op
= MQueryOp::RegExp
;
1025 queryExpression
.getExpressions().push_back( new MQueryExpressionString( columnName
, op
, matchString
));
1027 else if (SQL_ISRULE(parseTree
,test_for_null
))
1029 OSL_ENSURE(parseTree
->count() == 2,"Error in ParseTree");
1030 const OSQLParseNode
* pPart2
= parseTree
->getChild(1);
1031 OSL_ENSURE(SQL_ISTOKEN(pPart2
->getChild(0),IS
),"Error in ParseTree");
1033 if (!SQL_ISRULE(parseTree
->getChild(0),column_ref
))
1035 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_IS_NULL_COLUMN
, *this );
1038 if (SQL_ISTOKEN(pPart2
->getChild(1),NOT
))
1040 op
= MQueryOp::Exists
;
1044 op
= MQueryOp::DoesNotExist
;
1047 OUString sTableRange
;
1048 m_pSQLIterator
->getColumnRange(parseTree
->getChild(0),columnName
,sTableRange
);
1050 queryExpression
.getExpressions().push_back( new MQueryExpressionString( columnName
, op
));
1054 OSL_TRACE( "Unexpected statement!!!" );
1056 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
1062 void OResultSet::fillRowData()
1063 throw( ::com::sun::star::sdbc::SQLException
)
1065 OSL_ENSURE( m_pStatement
, "Require a statement" );
1067 MQueryExpression queryExpression
;
1069 OConnection
* xConnection
= static_cast<OConnection
*>(m_pStatement
->getConnection().get());
1070 m_xColumns
= m_pSQLIterator
->getSelectColumns();
1072 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
1074 OSQLColumns::Vector::const_iterator aIter
= m_xColumns
->get().begin();
1075 const OUString sProprtyName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
);
1077 m_aAttributeStrings
.clear();
1078 m_aAttributeStrings
.reserve(m_xColumns
->get().size());
1079 for (sal_Int32 i
= 1; aIter
!= m_xColumns
->get().end();++aIter
, i
++)
1081 (*aIter
)->getPropertyValue(sProprtyName
) >>= sName
;
1082 #if OSL_DEBUG_LEVEL > 0
1083 OSL_TRACE("Query Columns : (%d) %s", i
, OUtoCStr(sName
) );
1085 m_aAttributeStrings
.push_back( sName
);
1088 // Generate Match Conditions for Query
1089 const OSQLParseNode
* pParseTree
= m_pSQLIterator
->getWhereTree();
1091 m_bIsAlwaysFalseQuery
= false;
1092 if ( pParseTree
!= NULL
)
1094 // Extract required info
1096 OSL_TRACE("\tHave a Where Clause");
1098 analyseWhereClause( pParseTree
, queryExpression
);
1100 // If the query is a 0=1 then set Row count to 0 and return
1101 if ( m_bIsAlwaysFalseQuery
)
1107 m_aQueryHelper
.setExpression( queryExpression
);
1109 OUString
aStr( m_pTable
->getName() );
1110 m_aQueryHelper
.setAddressbook( aStr
);
1112 sal_Int32 rv
= m_aQueryHelper
.executeQuery(xConnection
);
1114 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERR_EXECUTING_QUERY
, *this );
1117 if (m_aQueryHelper
.hadError())
1119 m_pStatement
->getOwnConnection()->throwSQLException( m_aQueryHelper
.getError(), *this );
1122 //determine whether the address book is readonly
1123 determineReadOnly();
1125 #if OSL_DEBUG_LEVEL > 0
1126 OSL_TRACE( "executeQuery returned %d", rv
);
1128 OSL_TRACE( "\tOUT OResultSet::fillRowData()" );
1133 static bool matchRow( OValueRow
& row1
, OValueRow
& row2
)
1135 OValueVector::Vector::iterator row1Iter
= row1
->get().begin();
1136 OValueVector::Vector::iterator row2Iter
= row2
->get().begin();
1137 for ( ++row1Iter
,++row2Iter
; // the first column is the bookmark column
1138 row1Iter
!= row1
->get().end(); ++row1Iter
,++row2Iter
)
1140 if ( row1Iter
->isBound())
1142 // Compare values, if at anytime there's a mismatch return false
1143 if ( !( (*row1Iter
) == (*row2Iter
) ) )
1148 // If we get to here the rows match
1152 sal_Int32
OResultSet::getRowForCardNumber(sal_Int32 nCardNum
)
1154 OSL_TRACE("In/Out: OResultSet::getRowForCardNumber, nCardNum = %u", nCardNum
);
1156 if ( m_pKeySet
.is() )
1159 for(nPos
=0;nPos
< (sal_Int32
)m_pKeySet
->get().size();nPos
++)
1161 if (nCardNum
== (m_pKeySet
->get())[nPos
])
1163 OSL_TRACE("In/Out: OResultSet::getRowForCardNumber, return = %u", nPos
+1 );
1169 m_pStatement
->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK
, *this );
1175 void SAL_CALL
OResultSet::executeQuery() throw( ::com::sun::star::sdbc::SQLException
,
1176 ::com::sun::star::uno::RuntimeException
)
1178 ResultSetEntryGuard
aGuard( *this );
1180 OSL_ENSURE( m_pTable
, "Need a Table object");
1183 const OSQLTables
& xTabs
= m_pSQLIterator
->getTables();
1184 if ((xTabs
.begin() == xTabs
.end()) || !xTabs
.begin()->second
.is())
1185 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
1187 m_pTable
= static_cast< OTable
* > ((xTabs
.begin()->second
).get());
1195 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
1197 switch( m_pSQLIterator
->getStatementType() )
1199 case SQL_STATEMENT_SELECT
:
1201 if(m_bIsAlwaysFalseQuery
) {
1206 m_pStatement
->getOwnConnection()->throwSQLException( STR_NO_COUNT_SUPPORT
, *this );
1210 bool bDistinct
= false;
1211 OSQLParseNode
*pDistinct
= m_pParseTree
->getChild(1);
1212 if (pDistinct
&& pDistinct
->getTokenID() == SQL_TOKEN_DISTINCT
)
1216 m_aOrderbyColumnNumber
.push_back(m_aColMapping
[1]);
1217 m_aOrderbyAscending
.push_back(SQL_DESC
);
1222 OSortIndex::TKeyTypeVector
eKeyType(m_aOrderbyColumnNumber
.size());
1223 ::std::vector
<sal_Int32
>::iterator aOrderByIter
= m_aOrderbyColumnNumber
.begin();
1224 for ( ::std::vector
<sal_Int16
>::size_type i
= 0; aOrderByIter
!= m_aOrderbyColumnNumber
.end(); ++aOrderByIter
,++i
)
1226 OSL_ENSURE((sal_Int32
)m_aRow
->get().size() > *aOrderByIter
,"Invalid Index");
1227 switch ((m_aRow
->get().begin()+*aOrderByIter
)->getTypeKind())
1229 case DataType::CHAR
:
1230 case DataType::VARCHAR
:
1231 eKeyType
[i
] = SQL_ORDERBYKEY_STRING
;
1234 case DataType::OTHER
:
1235 case DataType::TINYINT
:
1236 case DataType::SMALLINT
:
1237 case DataType::INTEGER
:
1238 case DataType::DECIMAL
:
1239 case DataType::NUMERIC
:
1240 case DataType::REAL
:
1241 case DataType::DOUBLE
:
1242 case DataType::DATE
:
1243 case DataType::TIME
:
1244 case DataType::TIMESTAMP
:
1246 eKeyType
[i
] = SQL_ORDERBYKEY_DOUBLE
;
1249 // Other types aren't implemented (so they are always FALSE)
1251 eKeyType
[i
] = SQL_ORDERBYKEY_NONE
;
1252 OSL_FAIL("MResultSet::executeQuery: Order By Data Type not implemented");
1259 // Implement Sorting
1261 // So that we can sort we need to wait until the executed
1262 // query to the mozilla addressbooks has returned all
1265 OSL_TRACE("Query is to be sorted");
1267 OSL_ENSURE( m_aQueryHelper
.queryComplete(), "Query not complete!!");
1269 m_pSortIndex
= new OSortIndex(eKeyType
,m_aOrderbyAscending
);
1271 OSL_TRACE("OrderbyColumnNumber->size() = %zu",m_aOrderbyColumnNumber
.size());
1272 #if OSL_DEBUG_LEVEL > 0
1273 for ( ::std::vector
<sal_Int32
>::size_type i
= 0; i
< m_aColMapping
.size(); i
++ )
1274 OSL_TRACE("Mapped: %d -> %d", i
, m_aColMapping
[i
] );
1276 for ( sal_Int32 nRow
= 1; nRow
<= m_aQueryHelper
.getResultCount(); nRow
++ ) {
1278 OKeyValue
* pKeyValue
= OKeyValue::createKeyValue((nRow
));
1280 ::std::vector
<sal_Int32
>::iterator aIter
= m_aOrderbyColumnNumber
.begin();
1281 for (;aIter
!= m_aOrderbyColumnNumber
.end(); ++aIter
)
1283 const ORowSetValue
& value
= getValue(nRow
, *aIter
);
1285 OSL_TRACE( "Adding Value: (%d,%d) : %s", nRow
, *aIter
,OUtoCStr( value
));
1287 pKeyValue
->pushKey(new ORowSetValueDecorator(value
));
1290 m_pSortIndex
->AddKeyValue( pKeyValue
);
1293 m_pKeySet
= m_pSortIndex
->CreateKeySet();
1294 m_CurrentRowCount
= static_cast<sal_Int32
>(m_pKeySet
->get().size());
1295 #if OSL_DEBUG_LEVEL > 0
1296 for( OKeySet::Vector::size_type i
= 0; i
< m_pKeySet
->get().size(); i
++ )
1297 OSL_TRACE("Sorted: %d -> %d", i
, (m_pKeySet
->get())[i
] );
1300 m_pSortIndex
= NULL
;
1301 beforeFirst(); // Go back to start
1303 else //we always need m_pKeySet now
1304 m_pKeySet
= new OKeySet();
1306 // Handle the DISTINCT case
1307 if ( bDistinct
&& m_pKeySet
.is() )
1309 OValueRow aSearchRow
= new OValueVector( m_aRow
->get().size() );
1311 for( OKeySet::Vector::size_type i
= 0; i
< m_pKeySet
->get().size(); i
++ )
1313 fetchRow( (m_pKeySet
->get())[i
] ); // Fills m_aRow
1314 if ( matchRow( m_aRow
, aSearchRow
) )
1316 (m_pKeySet
->get())[i
] = 0; // Marker for later to be removed
1320 // They don't match, so it's not a duplicate.
1321 // Use the current Row as the next one to match against
1322 *aSearchRow
= *m_aRow
;
1325 // Now remove any keys marked with a 0
1326 m_pKeySet
->get().erase(::std::remove_if(m_pKeySet
->get().begin(),m_pKeySet
->get().end()
1327 ,::std::bind2nd(::std::equal_to
<sal_Int32
>(),0))
1328 ,m_pKeySet
->get().end());
1334 case SQL_STATEMENT_UPDATE
:
1335 case SQL_STATEMENT_DELETE
:
1336 case SQL_STATEMENT_INSERT
:
1339 m_pStatement
->getOwnConnection()->throwSQLException( STR_STMT_TYPE_NOT_SUPPORTED
, *this );
1347 void OResultSet::setBoundedColumns(const OValueRow
& _rRow
,
1348 const ::rtl::Reference
<connectivity::OSQLColumns
>& _rxColumns
,
1349 const Reference
<XIndexAccess
>& _xNames
,
1350 bool _bSetColumnMapping
,
1351 const Reference
<XDatabaseMetaData
>& _xMetaData
,
1352 ::std::vector
<sal_Int32
>& _rColMapping
)
1354 ::comphelper::UStringMixEqual
aCase(_xMetaData
->supportsMixedCaseQuotedIdentifiers());
1356 Reference
<XPropertySet
> xTableColumn
;
1357 OUString sTableColumnName
, sSelectColumnRealName
;
1359 const OUString sName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
);
1360 const OUString sRealName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME
);
1362 ::std::vector
< OUString
> aColumnNames
;
1363 aColumnNames
.reserve(_rxColumns
->get().size());
1364 OValueVector::Vector::iterator aRowIter
= _rRow
->get().begin()+1;
1365 for (sal_Int32 i
=0; // the first column is the bookmark column
1366 aRowIter
!= _rRow
->get().end();
1372 // get the table column and its name
1373 _xNames
->getByIndex(i
) >>= xTableColumn
;
1374 OSL_ENSURE(xTableColumn
.is(), "OResultSet::setBoundedColumns: invalid table column!");
1375 if (xTableColumn
.is())
1376 xTableColumn
->getPropertyValue(sName
) >>= sTableColumnName
;
1378 sTableColumnName
= "";
1380 // look if we have such a select column
1381 // TODO: would like to have a O(log n) search here ...
1382 sal_Int32 nColumnPos
= 0;
1383 for ( OSQLColumns::Vector::iterator aIter
= _rxColumns
->get().begin();
1384 aIter
!= _rxColumns
->get().end();
1385 ++aIter
,++nColumnPos
1388 if ( nColumnPos
< (sal_Int32
)aColumnNames
.size() )
1389 sSelectColumnRealName
= aColumnNames
[nColumnPos
];
1392 if((*aIter
)->getPropertySetInfo()->hasPropertyByName(sRealName
))
1393 (*aIter
)->getPropertyValue(sRealName
) >>= sSelectColumnRealName
;
1395 (*aIter
)->getPropertyValue(sName
) >>= sSelectColumnRealName
;
1396 aColumnNames
.push_back(sSelectColumnRealName
);
1399 if (aCase(sTableColumnName
, sSelectColumnRealName
))
1401 if(_bSetColumnMapping
)
1403 sal_Int32 nSelectColumnPos
= static_cast<sal_Int32
>(aIter
- _rxColumns
->get().begin() + 1);
1404 // the getXXX methods are 1-based ...
1405 sal_Int32 nTableColumnPos
= i
+ 1;
1406 // get first table column is the bookmark column
1408 #if OSL_DEBUG_LEVEL > 0
1409 OSL_TRACE("Set Col Mapping: %d -> %d", nSelectColumnPos
, nTableColumnPos
);
1411 _rColMapping
[nSelectColumnPos
] = nTableColumnPos
;
1414 aRowIter
->setBound(true);
1415 aRowIter
->setTypeKind(DataType::VARCHAR
);
1421 OSL_FAIL("OResultSet::setBoundedColumns: caught an Exception!");
1428 bool OResultSet::isCount() const
1430 return (m_pParseTree
&&
1431 m_pParseTree
->count() > 2 &&
1432 SQL_ISRULE(m_pParseTree
->getChild(2),scalar_exp_commalist
) &&
1433 SQL_ISRULE(m_pParseTree
->getChild(2)->getChild(0),derived_column
) &&
1434 SQL_ISRULE(m_pParseTree
->getChild(2)->getChild(0)->getChild(0),general_set_fct
) &&
1435 m_pParseTree
->getChild(2)->getChild(0)->getChild(0)->count() == 4
1441 // Check for valid row in m_aQuery
1443 bool OResultSet::validRow( sal_uInt32 nRow
)
1445 sal_Int32 nNumberOfRecords
= m_aQueryHelper
.getResultCount();
1447 while ( nRow
> (sal_uInt32
)nNumberOfRecords
&& !m_aQueryHelper
.queryComplete() ) {
1448 #if OSL_DEBUG_LEVEL > 0
1449 OSL_TRACE("validRow: waiting...");
1451 if (m_aQueryHelper
.checkRowAvailable( nRow
) == false)
1453 OSL_TRACE("validRow(%u): return False", nRow
);
1457 if ( m_aQueryHelper
.hadError() )
1459 m_pStatement
->getOwnConnection()->throwSQLException( m_aQueryHelper
.getError(), *this );
1462 nNumberOfRecords
= m_aQueryHelper
.getResultCount();
1465 if (( nRow
== 0 ) ||
1466 ( nRow
> (sal_uInt32
)nNumberOfRecords
&& m_aQueryHelper
.queryComplete()) ){
1467 OSL_TRACE("validRow(%u): return False", nRow
);
1470 #if OSL_DEBUG_LEVEL > 0
1471 OSL_TRACE("validRow(%u): return True", nRow
);
1476 bool OResultSet::fillKeySet(sal_Int32 nMaxCardNumber
)
1478 impl_ensureKeySet();
1479 if (m_CurrentRowCount
< nMaxCardNumber
)
1481 sal_Int32 nKeyValue
;
1482 if ( (sal_Int32
)m_pKeySet
->get().capacity() < nMaxCardNumber
)
1483 m_pKeySet
->get().reserve(nMaxCardNumber
+ 20 );
1485 for (nKeyValue
= m_CurrentRowCount
+1; nKeyValue
<= nMaxCardNumber
; nKeyValue
++)
1486 m_pKeySet
->get().push_back( nKeyValue
);
1487 m_CurrentRowCount
= nMaxCardNumber
;
1492 sal_Int32
OResultSet::deletedCount()
1494 impl_ensureKeySet();
1495 return m_CurrentRowCount
- static_cast<sal_Int32
>(m_pKeySet
->get().size());
1499 bool OResultSet::seekRow( eRowPosition pos
, sal_Int32 nOffset
)
1501 ResultSetEntryGuard
aGuard( *this );
1502 if ( !m_pKeySet
.is() )
1503 m_pStatement
->getOwnConnection()->throwSQLException( STR_ILLEGAL_MOVEMENT
, *this );
1505 sal_Int32 nNumberOfRecords
= m_aQueryHelper
.getResultCount();
1506 sal_Int32 nRetrievedRows
= currentRowCount();
1507 sal_Int32 nCurPos
= m_nRowPos
;
1509 OSL_TRACE("seekRow: nCurPos = %d", nCurPos
);
1512 OSL_TRACE("seekRow: NEXT");
1516 OSL_TRACE("seekRow: PRIOR");
1522 OSL_TRACE("seekRow: FIRST");
1527 OSL_TRACE("seekRow: LAST");
1528 nCurPos
= nRetrievedRows
;
1531 OSL_TRACE("seekRow: ABSOLUTE : %d", nOffset
);
1535 OSL_TRACE("seekRow: RELATIVE : %d", nOffset
);
1536 nCurPos
+= sal_uInt32( nOffset
);
1540 if ( nCurPos
<= 0 ) {
1542 OSL_TRACE("seekRow: return False, m_nRowPos = %u", m_nRowPos
);
1545 sal_Int32 nCurCard
= nCurPos
;
1546 if ( nCurPos
< (sal_Int32
)m_pKeySet
->get().size() ) //The requested row is exist in m_pKeySet, so we just use it
1548 nCurCard
= (m_pKeySet
->get())[nCurPos
-1];
1550 else //The requested row has not been retrieved until now. We should get the right card for it.
1551 nCurCard
= nCurPos
+ deletedCount();
1553 if ( nCurCard
> nNumberOfRecords
) {
1554 fillKeySet(nNumberOfRecords
);
1555 m_nRowPos
= static_cast<sal_uInt32
>(m_pKeySet
->get().size() + 1);
1556 OSL_TRACE("seekRow: return False, m_nRowPos = %u", m_nRowPos
);
1559 //Insert new retrieved items for later use
1560 fillKeySet(nNumberOfRecords
);
1561 m_nRowPos
= (sal_uInt32
)nCurPos
;
1562 OSL_TRACE("seekRow: return True, m_nRowPos = %u", m_nRowPos
);
1567 void OResultSet::setColumnMapping(const ::std::vector
<sal_Int32
>& _aColumnMapping
)
1569 m_aColMapping
= _aColumnMapping
;
1570 #if OSL_DEBUG_LEVEL > 0
1571 for ( sal_uInt32 i
= 0; i
< m_aColMapping
.size(); i
++ )
1572 OSL_TRACE("Set Mapped: %d -> %d", i
, m_aColMapping
[i
] );
1577 ::com::sun::star::uno::Any
OResultSet::getBookmark( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1579 OSL_TRACE("getBookmark, m_nRowPos = %u", m_nRowPos
);
1580 ResultSetEntryGuard
aGuard( *this );
1581 if ( fetchCurrentRow() == false ) {
1582 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1585 OSL_ENSURE((!m_aRow
->isDeleted()),"getBookmark called for deleted row");
1586 return makeAny((sal_Int32
)(m_aRow
->get())[0]);
1588 sal_Bool
OResultSet::moveToBookmark( const ::com::sun::star::uno::Any
& bookmark
) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1590 ResultSetEntryGuard
aGuard( *this );
1591 OSL_TRACE("moveToBookmark, bookmark = %u", comphelper::getINT32(bookmark
) );
1592 sal_Int32 nCardNum
= comphelper::getINT32(bookmark
);
1593 m_nRowPos
= getRowForCardNumber(nCardNum
);
1597 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
, std::exception
)
1599 ResultSetEntryGuard
aGuard( *this );
1600 OSL_TRACE("moveRelativeToBookmark, bookmark = %u rows= %u", comphelper::getINT32(bookmark
),rows
);
1601 sal_Int32 nCardNum
= comphelper::getINT32(bookmark
);
1602 m_nRowPos
= getRowForCardNumber(nCardNum
);
1603 return seekRow(RELATIVE_POS
,rows
);
1605 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
, std::exception
)
1607 ResultSetEntryGuard
aGuard( *this );
1608 OSL_TRACE("compareBookmarks, m_nRowPos = %u", m_nRowPos
);
1610 sal_Int32 nSecond
=0;
1611 sal_Int32 nResult
=0;
1613 if ( !( lhs
>>= nFirst
) || !( rhs
>>= nSecond
) ) {
1614 m_pStatement
->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK
, *this );
1617 if(nFirst
< nSecond
)
1619 else if(nFirst
> nSecond
)
1626 sal_Bool
OResultSet::hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1628 ResultSetEntryGuard
aGuard( *this );
1629 OSL_TRACE("hasOrderedBookmarks, m_nRowPos = %u", m_nRowPos
);
1632 sal_Int32
OResultSet::hashBookmark( const ::com::sun::star::uno::Any
& bookmark
) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1634 ResultSetEntryGuard
aGuard( *this );
1635 OSL_TRACE("hashBookmark, m_nRowPos = %u", m_nRowPos
);
1636 return comphelper::getINT32(bookmark
);
1639 sal_Int32
OResultSet::getCurrentCardNumber()
1641 if ( ( m_nRowPos
== 0 ) || !m_pKeySet
.is() )
1643 if (m_pKeySet
->get().size() < m_nRowPos
)
1645 return (m_pKeySet
->get())[m_nRowPos
-1];
1647 void OResultSet::checkPendingUpdate() throw(SQLException
, RuntimeException
)
1649 OSL_FAIL( "OResultSet::checkPendingUpdate() not implemented" );
1651 OSL_TRACE("checkPendingUpdate, m_nRowPos = %u", m_nRowPos );
1652 const sal_Int32 nCurrentRow = getCurrentCardNumber();
1654 if ((m_nNewRow && nCurrentRow != m_nNewRow)
1655 || ( m_nUpdatedRow && m_nUpdatedRow != nCurrentRow))
1657 const OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1659 "$position$", OUString::valueOf(nCurrentRow)
1661 ::dbtools::throwGenericSQLException(sError,*this);
1666 void OResultSet::updateValue(sal_Int32 columnIndex
,const ORowSetValue
& x
) throw(SQLException
, RuntimeException
)
1668 OSL_TRACE("updateValue, m_nRowPos = %u", m_nRowPos
);
1669 ResultSetEntryGuard
aGuard( *this );
1670 if ( fetchCurrentRow() == false ) {
1671 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1674 checkPendingUpdate();
1676 checkIndex(columnIndex
);
1677 columnIndex
= mapColumn(columnIndex
);
1679 (m_aRow
->get())[columnIndex
].setBound(true);
1680 (m_aRow
->get())[columnIndex
] = x
;
1681 m_nUpdatedRow
= getCurrentCardNumber();
1682 // m_RowStates = m_RowStates | RowStates_Updated;
1686 void SAL_CALL
OResultSet::updateNull( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
1688 OSL_TRACE("updateNull, m_nRowPos = %u", m_nRowPos
);
1689 ResultSetEntryGuard
aGuard( *this );
1690 if ( fetchCurrentRow() == false )
1691 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1693 checkPendingUpdate();
1694 checkIndex(columnIndex
);
1695 columnIndex
= mapColumn(columnIndex
);
1697 (m_aRow
->get())[columnIndex
].setBound(true);
1698 (m_aRow
->get())[columnIndex
].setNull();
1699 m_nUpdatedRow
= getCurrentCardNumber();
1700 // m_RowStates = m_RowStates | RowStates_Updated;
1704 void SAL_CALL
OResultSet::updateBoolean( sal_Int32 columnIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
, std::exception
)
1706 updateValue(columnIndex
, static_cast<bool>(x
));
1709 void SAL_CALL
OResultSet::updateByte( sal_Int32 columnIndex
, sal_Int8 x
) throw(SQLException
, RuntimeException
, std::exception
)
1711 updateValue(columnIndex
,x
);
1715 void SAL_CALL
OResultSet::updateShort( sal_Int32 columnIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
, std::exception
)
1717 updateValue(columnIndex
,x
);
1720 void SAL_CALL
OResultSet::updateInt( sal_Int32 columnIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
, std::exception
)
1722 updateValue(columnIndex
,x
);
1725 void SAL_CALL
OResultSet::updateLong( sal_Int32
/*columnIndex*/, sal_Int64
/*x*/ ) throw(SQLException
, RuntimeException
, std::exception
)
1727 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::updateLong", *this );
1730 void SAL_CALL
OResultSet::updateFloat( sal_Int32 columnIndex
, float x
) throw(SQLException
, RuntimeException
, std::exception
)
1732 updateValue(columnIndex
,x
);
1736 void SAL_CALL
OResultSet::updateDouble( sal_Int32 columnIndex
, double x
) throw(SQLException
, RuntimeException
, std::exception
)
1738 updateValue(columnIndex
,x
);
1741 void SAL_CALL
OResultSet::updateString( sal_Int32 columnIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1743 updateValue(columnIndex
,x
);
1746 void SAL_CALL
OResultSet::updateBytes( sal_Int32 columnIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
, std::exception
)
1748 updateValue(columnIndex
,x
);
1751 void SAL_CALL
OResultSet::updateDate( sal_Int32 columnIndex
, const ::com::sun::star::util::Date
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1753 updateValue(columnIndex
,x
);
1757 void SAL_CALL
OResultSet::updateTime( sal_Int32 columnIndex
, const ::com::sun::star::util::Time
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1759 updateValue(columnIndex
,x
);
1763 void SAL_CALL
OResultSet::updateTimestamp( sal_Int32 columnIndex
, const ::com::sun::star::util::DateTime
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1765 updateValue(columnIndex
,x
);
1769 void SAL_CALL
OResultSet::updateBinaryStream( sal_Int32 columnIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
1771 ResultSetEntryGuard
aGuard( *this );
1774 ::dbtools::throwFunctionSequenceException(*this);
1776 Sequence
<sal_Int8
> aSeq
;
1777 x
->readBytes(aSeq
,length
);
1778 updateValue(columnIndex
,aSeq
);
1781 void SAL_CALL
OResultSet::updateCharacterStream( sal_Int32 columnIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
1783 updateBinaryStream(columnIndex
,x
,length
);
1786 void SAL_CALL
OResultSet::updateObject( sal_Int32 columnIndex
, const Any
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1788 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1790 const OUString
sError( m_pStatement
->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1791 STR_COLUMN_NOT_UPDATEABLE
,
1792 "$position$", OUString::number(columnIndex
)
1794 ::dbtools::throwGenericSQLException(sError
,*this);
1795 } // if (!::dbtools::implUpdateObject(this, columnIndex, x))
1799 void SAL_CALL
OResultSet::updateNumericObject( sal_Int32 columnIndex
, const Any
& x
, sal_Int32
/*scale*/ ) throw(SQLException
, RuntimeException
, std::exception
)
1801 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1803 const OUString
sError( m_pStatement
->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1804 STR_COLUMN_NOT_UPDATEABLE
,
1805 "$position$", OUString::number(columnIndex
)
1807 ::dbtools::throwGenericSQLException(sError
,*this);
1813 void SAL_CALL
OResultSet::insertRow( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1815 ResultSetEntryGuard
aGuard( *this );
1816 OSL_TRACE("insertRow in, m_nRowPos = %u", m_nRowPos
);
1817 // m_RowStates = RowStates_Inserted;
1821 //m_aQueryHelper.setRowStates(getCurrentCardNumber(),m_RowStates);
1822 OSL_TRACE("insertRow out, m_nRowPos = %u", m_nRowPos
);
1825 void SAL_CALL
OResultSet::updateRow( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1827 OSL_FAIL( "OResultSet::updateRow( ) not implemented" );
1830 void SAL_CALL
OResultSet::deleteRow( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1832 OSL_FAIL( "OResultSet::deleteRow( ) not implemented" );
1835 void SAL_CALL
OResultSet::cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1837 OSL_FAIL( "OResultSet::cancelRowUpdates( ) not implemented" );
1840 void SAL_CALL
OResultSet::moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1842 OSL_FAIL( "OResultSet::moveToInsertRow( ) not implemented" );
1845 void SAL_CALL
OResultSet::moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
1847 ResultSetEntryGuard
aGuard( *this );
1848 OSL_TRACE("moveToCurrentRow, m_nRowPos = %u", m_nRowPos
);
1851 m_nRowPos
= m_nOldRowPos
;
1856 bool OResultSet::determineReadOnly()
1858 // OSL_FAIL( "OResultSet::determineReadOnly( ) not implemented" );
1860 if (m_bIsReadOnly
== -1)
1862 m_bIsReadOnly
= sal_True
;
1863 // OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
1864 // m_bIsReadOnly = !m_aQueryHelper.isWritable(xConnection) || m_bIsAlwaysFalseQuery;
1867 return m_bIsReadOnly
!= 0;
1870 void OResultSet::setTable(OTable
* _rTable
)
1872 OSL_TRACE("In : setTable");
1874 m_pTable
->acquire();
1875 m_xTableColumns
= m_pTable
->getColumns();
1876 if(m_xTableColumns
.is())
1877 m_aColumnNames
= m_xTableColumns
->getElementNames();
1878 OSL_TRACE("Out : setTable");
1881 void OResultSet::setOrderByColumns(const ::std::vector
<sal_Int32
>& _aColumnOrderBy
)
1883 m_aOrderbyColumnNumber
= _aColumnOrderBy
;
1886 void OResultSet::setOrderByAscending(const ::std::vector
<TAscendingOrder
>& _aOrderbyAsc
)
1888 m_aOrderbyAscending
= _aOrderbyAsc
;
1890 Sequence
< sal_Int32
> SAL_CALL
OResultSet::deleteRows( const Sequence
< Any
>& /*rows*/ ) throw(SQLException
, RuntimeException
, std::exception
)
1892 ::dbtools::throwFeatureNotImplementedException( "XDeleteRows::deleteRows", *this );
1893 return Sequence
< sal_Int32
>();
1896 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */