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/ResultSetType.hpp>
21 #include <com/sun/star/sdbc/FetchDirection.hpp>
22 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
23 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
24 #include <com/sun/star/beans/PropertyAttribute.hpp>
25 #include <connectivity/dbtools.hxx>
26 #include <comphelper/types.hxx>
27 #include <cppuhelper/typeprovider.hxx>
28 #include <sal/log.hxx>
32 #include "MResultSet.hxx"
33 #include <sqlbison.hxx>
34 #include "MResultSetMetaData.hxx"
35 #include <FDatabaseMetaDataResultSet.hxx>
37 #include <strings.hrc>
39 using namespace ::comphelper
;
40 using namespace connectivity
;
41 using namespace connectivity::mork
;
42 using namespace ::cppu
;
43 using namespace com::sun::star::uno
;
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::beans
;
46 using namespace com::sun::star::sdbc
;
47 using namespace com::sun::star::sdbcx
;
48 using namespace com::sun::star::container
;
49 using namespace com::sun::star::io
;
50 using namespace com::sun::star::util
;
53 // IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
54 OUString SAL_CALL
OResultSet::getImplementationName( )
56 return OUString("com.sun.star.sdbcx.mork.ResultSet");
59 Sequence
< OUString
> SAL_CALL
OResultSet::getSupportedServiceNames( )
61 return {"com.sun.star.sdbc.ResultSet","com.sun.star.sdbcx.ResultSet"};
64 sal_Bool SAL_CALL
OResultSet::supportsService( const OUString
& _rServiceName
)
66 return cppu::supportsService(this, _rServiceName
);
70 OResultSet::OResultSet(OCommonStatement
* pStmt
, const std::shared_ptr
< connectivity::OSQLParseTreeIterator
>& _pSQLIterator
)
71 : OResultSet_BASE(m_aMutex
)
72 ,OPropertySetHelper(OResultSet_BASE::rBHelper
)
77 ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE
)
78 ,m_nFetchDirection(FetchDirection::FORWARD
)
79 ,m_pSQLIterator( _pSQLIterator
)
80 ,m_pParseTree( _pSQLIterator
->getParseTree() )
81 ,m_aQueryHelper(pStmt
->getOwnConnection()->getColumnAlias())
84 ,m_bIsAlwaysFalseQuery(false)
85 ,m_bIsReadOnly(TRISTATE_INDET
)
87 //m_aQuery.setMaxNrOfReturns(pStmt->getOwnConnection()->getMaxResultRecords());
90 OResultSet::~OResultSet()
95 void OResultSet::disposing()
97 OPropertySetHelper::disposing();
99 ::osl::MutexGuard
aGuard(m_aMutex
);
101 m_xStatement
.clear();
103 m_pParseTree
= nullptr;
104 m_xColumns
= nullptr;
109 Any SAL_CALL
OResultSet::queryInterface( const Type
& rType
)
111 Any aRet
= OPropertySetHelper::queryInterface(rType
);
113 aRet
= OResultSet_BASE::queryInterface(rType
);
117 Sequence
< Type
> SAL_CALL
OResultSet::getTypes( )
119 OTypeCollection
aTypes( cppu::UnoType
<css::beans::XMultiPropertySet
>::get(),
120 cppu::UnoType
<css::beans::XFastPropertySet
>::get(),
121 cppu::UnoType
<css::beans::XPropertySet
>::get());
123 return ::comphelper::concatSequences(aTypes
.getTypes(),OResultSet_BASE::getTypes());
126 void OResultSet::methodEntry()
128 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
129 if ( !m_xTable
.is() )
131 OSL_FAIL( "OResultSet::methodEntry: looks like we're disposed, but how is this possible?" );
132 throw DisposedException( OUString(), *this );
137 sal_Int32 SAL_CALL
OResultSet::findColumn( const OUString
& columnName
)
139 ResultSetEntryGuard
aGuard( *this );
141 // find the first column with the name columnName
142 Reference
< XResultSetMetaData
> xMeta
= getMetaData();
143 sal_Int32 nLen
= xMeta
->getColumnCount();
147 if(xMeta
->isCaseSensitive(i
) ? columnName
== xMeta
->getColumnName(i
) :
148 columnName
.equalsIgnoreAsciiCase(xMeta
->getColumnName(i
)))
152 ::dbtools::throwInvalidColumnException( columnName
, *this );
154 return 0; // Never reached
157 Reference
< XInputStream
> SAL_CALL
OResultSet::getBinaryStream( sal_Int32
/*columnIndex*/ )
162 Reference
< XInputStream
> SAL_CALL
OResultSet::getCharacterStream( sal_Int32
/*columnIndex*/ )
168 sal_Bool SAL_CALL
OResultSet::getBoolean( sal_Int32
/*columnIndex*/ )
170 ResultSetEntryGuard
aGuard( *this );
176 sal_Int8 SAL_CALL
OResultSet::getByte( sal_Int32
/*columnIndex*/ )
182 Sequence
< sal_Int8
> SAL_CALL
OResultSet::getBytes( sal_Int32
/*columnIndex*/ )
184 return Sequence
< sal_Int8
>();
188 Date SAL_CALL
OResultSet::getDate( sal_Int32
/*columnIndex*/ )
194 double SAL_CALL
OResultSet::getDouble( sal_Int32
/*columnIndex*/ )
200 float SAL_CALL
OResultSet::getFloat( sal_Int32
/*columnIndex*/ )
206 sal_Int32 SAL_CALL
OResultSet::getInt( sal_Int32
/*columnIndex*/ )
212 sal_Int32 SAL_CALL
OResultSet::getRow( )
214 ResultSetEntryGuard
aGuard( *this );
216 SAL_INFO("connectivity.mork", "return = " << m_nRowPos
);
221 sal_Int64 SAL_CALL
OResultSet::getLong( sal_Int32
/*columnIndex*/ )
227 Reference
< XResultSetMetaData
> SAL_CALL
OResultSet::getMetaData( )
229 ResultSetEntryGuard
aGuard( *this );
231 if(!m_xMetaData
.is())
232 m_xMetaData
= new OResultSetMetaData(
233 m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
, m_xTable
.get(), determineReadOnly());
237 Reference
< XArray
> SAL_CALL
OResultSet::getArray( sal_Int32
/*columnIndex*/ )
243 Reference
< XClob
> SAL_CALL
OResultSet::getClob( sal_Int32
/*columnIndex*/ )
248 Reference
< XBlob
> SAL_CALL
OResultSet::getBlob( sal_Int32
/*columnIndex*/ )
254 Reference
< XRef
> SAL_CALL
OResultSet::getRef( sal_Int32
/*columnIndex*/ )
260 Any SAL_CALL
OResultSet::getObject( sal_Int32
/*columnIndex*/, const Reference
< css::container::XNameAccess
>& /*typeMap*/ )
266 sal_Int16 SAL_CALL
OResultSet::getShort( sal_Int32
/*columnIndex*/ )
272 void OResultSet::checkIndex(sal_Int32 columnIndex
)
274 if(columnIndex
<= 0 || columnIndex
> static_cast<sal_Int32
>(m_xColumns
->get().size()))
275 ::dbtools::throwInvalidIndexException(*this);
278 sal_uInt32
OResultSet::currentRowCount()
280 if ( m_bIsAlwaysFalseQuery
)
282 //return 0;//m_aQuery.getRealRowCount() - deletedCount();
283 // new implementation
284 return m_aQueryHelper
.getResultCount();
288 bool OResultSet::fetchCurrentRow( )
290 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
291 return fetchRow(getCurrentCardNumber());
295 bool OResultSet::fetchRow(sal_Int32 cardNumber
,bool bForceReload
)
297 SAL_INFO("connectivity.mork", "cardNumber = " << cardNumber
);
300 // Check whether we've already fetched the row...
301 if ( !(m_aRow
->get())[0].isNull() && static_cast<sal_Int32
>((m_aRow
->get())[0]) == cardNumber
)
305 // m_aQuery.resyncRow(cardNumber);
307 if ( !validRow( cardNumber
) )
310 (m_aRow
->get())[0] = cardNumber
;
311 sal_Int32 nCount
= m_aColumnNames
.getLength();
312 //m_RowStates = m_aQuery.getRowStates(cardNumber);
313 for( sal_Int32 i
= 1; i
<= nCount
; i
++ )
315 if ( (m_aRow
->get())[i
].isBound() )
318 // Everything in the addressbook is a string!
320 if ( !m_aQueryHelper
.getRowValue( (m_aRow
->get())[i
], cardNumber
, m_aColumnNames
[i
-1], DataType::VARCHAR
))
322 m_pStatement
->getOwnConnection()->throwSQLException( m_aQueryHelper
.getError(), *this );
331 const ORowSetValue
& OResultSet::getValue(sal_Int32 cardNumber
, sal_Int32 columnIndex
)
333 if ( !fetchRow( cardNumber
) )
335 OSL_FAIL("fetchRow() returned False" );
337 return *ODatabaseMetaDataResultSet::getEmptyValue();
340 m_bWasNull
= (m_aRow
->get())[columnIndex
].isNull();
341 return (m_aRow
->get())[columnIndex
];
346 OUString SAL_CALL
OResultSet::getString( sal_Int32 columnIndex
)
348 ResultSetEntryGuard
aGuard( *this );
350 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
351 OSL_ENSURE(columnIndex
<= static_cast<sal_Int32
>(m_xColumns
->get().size()), "Trying to access invalid columns number");
352 checkIndex( columnIndex
);
354 // If this query was sorted then we should have a valid KeySet, so use it
355 return getValue(getCurrentCardNumber(), mapColumn( columnIndex
) );
360 Time SAL_CALL
OResultSet::getTime( sal_Int32
/*columnIndex*/ )
362 ResultSetEntryGuard
aGuard( *this );
367 DateTime SAL_CALL
OResultSet::getTimestamp( sal_Int32
/*columnIndex*/ )
369 ResultSetEntryGuard
aGuard( *this );
374 sal_Bool SAL_CALL
OResultSet::isBeforeFirst( )
376 ResultSetEntryGuard
aGuard( *this );
378 // here you have to implement your movements
379 // return true means there is no data
380 return( m_nRowPos
< 1 );
383 sal_Bool SAL_CALL
OResultSet::isAfterLast( )
385 SAL_WARN("connectivity.mork", "OResultSet::isAfterLast() NOT IMPLEMENTED!");
386 ResultSetEntryGuard
aGuard( *this );
388 return m_nRowPos
> currentRowCount();
391 sal_Bool SAL_CALL
OResultSet::isFirst( )
393 ResultSetEntryGuard
aGuard( *this );
395 return m_nRowPos
== 1;
398 sal_Bool SAL_CALL
OResultSet::isLast( )
400 SAL_WARN("connectivity.mork", "OResultSet::isLast() NOT IMPLEMENTED!");
401 ResultSetEntryGuard
aGuard( *this );
404 return m_nRowPos
== currentRowCount();
407 void SAL_CALL
OResultSet::beforeFirst( )
409 ResultSetEntryGuard
aGuard( *this );
411 // move before the first row so that isBeforeFirst returns false
416 void SAL_CALL
OResultSet::afterLast( )
418 ResultSetEntryGuard
aGuard( *this );
425 void SAL_CALL
OResultSet::close()
431 sal_Bool SAL_CALL
OResultSet::first( )
433 return seekRow( FIRST_POS
);
437 sal_Bool SAL_CALL
OResultSet::last( )
439 return seekRow( LAST_POS
);
442 sal_Bool SAL_CALL
OResultSet::absolute( sal_Int32 row
)
444 return seekRow( ABSOLUTE_POS
, row
);
447 sal_Bool SAL_CALL
OResultSet::relative( sal_Int32 row
)
449 return seekRow( RELATIVE_POS
, row
);
452 sal_Bool SAL_CALL
OResultSet::previous( )
454 ResultSetEntryGuard
aGuard( *this );
455 return seekRow( PRIOR_POS
);
458 Reference
< XInterface
> SAL_CALL
OResultSet::getStatement( )
460 ResultSetEntryGuard
aGuard( *this );
465 sal_Bool SAL_CALL
OResultSet::rowDeleted( )
467 SAL_WARN("connectivity.mork", "OResultSet::rowDeleted() NOT IMPLEMENTED!");
468 ResultSetEntryGuard
aGuard( *this );
469 return true;//return ((m_RowStates & RowStates_Deleted) == RowStates_Deleted) ;
472 sal_Bool SAL_CALL
OResultSet::rowInserted( )
474 SAL_WARN("connectivity.mork", "OResultSet::rowInserted() NOT IMPLEMENTED!");
475 ResultSetEntryGuard
aGuard( *this );
476 return true;//return ((m_RowStates & RowStates_Inserted) == RowStates_Inserted);
479 sal_Bool SAL_CALL
OResultSet::rowUpdated( )
481 SAL_WARN("connectivity.mork", "OResultSet::rowUpdated() NOT IMPLEMENTED!");
482 ResultSetEntryGuard
aGuard( *this );
483 return true;// return ((m_RowStates & RowStates_Updated) == RowStates_Updated) ;
487 sal_Bool SAL_CALL
OResultSet::next( )
489 return seekRow( NEXT_POS
);
493 sal_Bool SAL_CALL
OResultSet::wasNull( )
495 ResultSetEntryGuard
aGuard( *this );
501 void SAL_CALL
OResultSet::cancel( )
505 void SAL_CALL
OResultSet::clearWarnings( )
509 Any SAL_CALL
OResultSet::getWarnings( )
514 void SAL_CALL
OResultSet::refreshRow( )
516 if (fetchRow(getCurrentCardNumber(),true)) {
517 //force fetch current row will cause we lose all change to the current row
518 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_REFRESH_ROW
, *this );
522 IPropertyArrayHelper
* OResultSet::createArrayHelper( ) const
524 Sequence
< Property
> aProps(5);
525 Property
* pProperties
= aProps
.getArray();
527 pProperties
[nPos
++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION
),
528 PROPERTY_ID_FETCHDIRECTION
, cppu::UnoType
<sal_Int32
>::get(), 0);
530 pProperties
[nPos
++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE
),
531 PROPERTY_ID_FETCHSIZE
, cppu::UnoType
<sal_Int32
>::get(), 0);
533 pProperties
[nPos
++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE
),
534 PROPERTY_ID_ISBOOKMARKABLE
, cppu::UnoType
<bool>::get(), PropertyAttribute::READONLY
);
536 pProperties
[nPos
++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY
),
537 PROPERTY_ID_RESULTSETCONCURRENCY
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
539 pProperties
[nPos
++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE
),
540 PROPERTY_ID_RESULTSETTYPE
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
542 return new OPropertyArrayHelper(aProps
);
545 IPropertyArrayHelper
& OResultSet::getInfoHelper()
547 return *getArrayHelper();
550 sal_Bool
OResultSet::convertFastPropertyValue(
551 Any
& /*rConvertedValue*/,
554 const Any
& /*rValue*/ )
556 OSL_FAIL( "OResultSet::convertFastPropertyValue: not implemented!" );
559 case PROPERTY_ID_ISBOOKMARKABLE
:
560 case PROPERTY_ID_RESULTSETCONCURRENCY
:
561 case PROPERTY_ID_RESULTSETTYPE
:
562 throw css::lang::IllegalArgumentException();
563 case PROPERTY_ID_FETCHDIRECTION
:
564 case PROPERTY_ID_FETCHSIZE
:
571 void OResultSet::setFastPropertyValue_NoBroadcast(
573 const Any
& /*rValue*/
576 OSL_FAIL( "OResultSet::setFastPropertyValue_NoBroadcast: not implemented!" );
579 case PROPERTY_ID_ISBOOKMARKABLE
:
580 case PROPERTY_ID_RESULTSETCONCURRENCY
:
581 case PROPERTY_ID_RESULTSETTYPE
:
582 throw Exception("cannot set prop " + OUString::number(nHandle
), nullptr);
583 case PROPERTY_ID_FETCHDIRECTION
:
585 case PROPERTY_ID_FETCHSIZE
:
592 void OResultSet::getFastPropertyValue(
599 case PROPERTY_ID_RESULTSETCONCURRENCY
:
600 rValue
<<= sal_Int32(ResultSetConcurrency::UPDATABLE
);
602 case PROPERTY_ID_RESULTSETTYPE
:
603 rValue
<<= m_nResultSetType
;
605 case PROPERTY_ID_FETCHDIRECTION
:
606 rValue
<<= m_nFetchDirection
;
608 case PROPERTY_ID_FETCHSIZE
:
609 rValue
<<= sal_Int32(0);
611 case PROPERTY_ID_ISBOOKMARKABLE
:
612 const_cast< OResultSet
* >( this )->determineReadOnly();
613 rValue
<<= (m_bIsReadOnly
== TRISTATE_FALSE
);
618 void SAL_CALL
OResultSet::acquire() throw()
620 OResultSet_BASE::acquire();
623 void SAL_CALL
OResultSet::release() throw()
625 OResultSet_BASE::release();
628 css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
OResultSet::getPropertySetInfo( )
630 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
634 void OResultSet::parseParameter( const OSQLParseNode
* pNode
, OUString
& rMatchString
)
636 OSL_ENSURE(pNode
->count() > 0,"Error parsing parameter in Parse Tree");
637 OSQLParseNode
*pMark
= pNode
->getChild(0);
639 // Initialize to empty string
640 rMatchString
.clear();
642 OUString aParameterName
;
643 if (SQL_ISPUNCTUATION(pMark
,"?")) {
644 aParameterName
= "?";
646 else if (SQL_ISPUNCTUATION(pMark
,":")) {
647 aParameterName
= pNode
->getChild(1)->getTokenValue();
649 // XXX - Now we know name, what's value????
653 "Parameter name [" << m_nParamIndex
<< "]: " << aParameterName
);
655 if ( m_aParameterRow
.is() ) {
656 OSL_ENSURE( m_nParamIndex
< static_cast<sal_Int32
>(m_aParameterRow
->get().size()) + 1, "More parameters than values found" );
657 rMatchString
= (m_aParameterRow
->get())[static_cast<sal_uInt16
>(m_nParamIndex
)];
658 SAL_INFO("connectivity.mork", "Prop Value: " << rMatchString
);
661 SAL_INFO("connectivity.mork", "Prop Value: Invalid ParameterRow!");
666 #define ALT_WILDCARD "*"
667 static const sal_Unicode MATCHCHAR
= '_';
669 void OResultSet::analyseWhereClause( const OSQLParseNode
* parseTree
,
670 MQueryExpression
&queryExpression
)
673 MQueryOp::cond_type
op( MQueryOp::Is
);
674 OUString matchString
;
676 if ( parseTree
== nullptr )
679 if ( m_pSQLIterator
->getParseTree() != nullptr ) {
680 ::rtl::Reference
<OSQLColumns
> xColumns
= m_pSQLIterator
->getParameters();
683 OUString aColName
, aParameterValue
;
685 for (auto const& column
: xColumns
->get())
687 column
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
)) >>= aColName
;
688 SAL_INFO("connectivity.mork", "Prop Column Name: " << aColName
);
689 if ( m_aParameterRow
.is() ) {
690 aParameterValue
= (m_aParameterRow
->get())[static_cast<sal_uInt16
>(i
)];
691 SAL_INFO("connectivity.mork", "Prop Value: " << aParameterValue
);
694 SAL_INFO("connectivity.mork", "Prop Value: Invalid ParameterRow!");
702 if ( SQL_ISRULE(parseTree
,where_clause
) )
704 // Reset Parameter Counter
706 analyseWhereClause( parseTree
->getChild( 1 ), queryExpression
);
708 else if ( parseTree
->count() == 3 && // Handle ()'s
709 SQL_ISPUNCTUATION(parseTree
->getChild(0),"(") &&
710 SQL_ISPUNCTUATION(parseTree
->getChild(2),")"))
712 MQueryExpression
*subExpression
= new MQueryExpression();
713 analyseWhereClause( parseTree
->getChild( 1 ), *subExpression
);
714 queryExpression
.addExpression( subExpression
);
716 else if ((SQL_ISRULE(parseTree
,search_condition
) || SQL_ISRULE(parseTree
,boolean_term
))
717 && parseTree
->count() == 3) // Handle AND/OR
719 // TODO - Need to take care or AND, for now match is always OR
720 analyseWhereClause( parseTree
->getChild( 0 ), queryExpression
);
721 analyseWhereClause( parseTree
->getChild( 2 ), queryExpression
);
723 if (SQL_ISTOKEN(parseTree
->getChild(1),OR
)) { // OR-Operator
724 queryExpression
.setExpressionCondition( MQueryExpression::OR
);
726 else if (SQL_ISTOKEN(parseTree
->getChild(1),AND
)) { // AND-Operator
727 queryExpression
.setExpressionCondition( MQueryExpression::AND
);
730 OSL_FAIL("analyseSQL: Error in Parse Tree");
733 else if (SQL_ISRULE(parseTree
,comparison_predicate
))
735 OSL_ENSURE(parseTree
->count() == 3, "Error parsing COMPARE predicate");
736 if (!(SQL_ISRULE(parseTree
->getChild(0),column_ref
) ||
737 parseTree
->getChild(2)->getNodeType() == SQLNodeType::String
||
738 parseTree
->getChild(2)->getNodeType() == SQLNodeType::IntNum
||
739 parseTree
->getChild(2)->getNodeType() == SQLNodeType::ApproxNum
||
740 SQL_ISTOKEN(parseTree
->getChild(2),TRUE
) ||
741 SQL_ISTOKEN(parseTree
->getChild(2),FALSE
) ||
742 SQL_ISRULE(parseTree
->getChild(2),parameter
) ||
744 (SQL_ISRULE(parseTree
->getChild(2),set_fct_spec
) && SQL_ISPUNCTUATION(parseTree
->getChild(2)->getChild(0),"{"))))
746 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
749 OSQLParseNode
*pPrec
= parseTree
->getChild(1);
750 if (pPrec
->getNodeType() == SQLNodeType::Equal
)
752 else if (pPrec
->getNodeType() == SQLNodeType::NotEqual
)
753 op
= MQueryOp::IsNot
;
755 OUString sTableRange
;
756 if(SQL_ISRULE(parseTree
->getChild(0),column_ref
))
757 m_pSQLIterator
->getColumnRange(parseTree
->getChild(0),columnName
,sTableRange
);
758 else if(parseTree
->getChild(0)->isToken())
759 columnName
= parseTree
->getChild(0)->getTokenValue();
761 if ( SQL_ISRULE(parseTree
->getChild(2),parameter
) ) {
762 parseParameter( parseTree
->getChild(2), matchString
);
765 matchString
= parseTree
->getChild(2)->getTokenValue();
768 if ( columnName
== "0" && op
== MQueryOp::Is
&& matchString
== "1" ) {
769 m_bIsAlwaysFalseQuery
= true;
771 queryExpression
.addExpression( new MQueryExpressionString( columnName
, op
, matchString
));
773 else if (SQL_ISRULE(parseTree
,like_predicate
))
775 OSL_ENSURE(parseTree
->count() == 2, "Error parsing LIKE predicate");
777 if ( !SQL_ISRULE(parseTree
->getChild(0), column_ref
) )
779 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_COLUMN
, *this );
783 OSQLParseNode
*pColumn
;
784 OSQLParseNode
*pAtom
;
785 OSQLParseNode
*pOptEscape
;
786 const OSQLParseNode
* pPart2
= parseTree
->getChild(1);
787 pColumn
= parseTree
->getChild(0); // Match Item
788 pAtom
= pPart2
->getChild(static_cast<sal_uInt32
>(pPart2
->count()-2)); // Match String
789 pOptEscape
= pPart2
->getChild(static_cast<sal_uInt32
>(pPart2
->count()-1)); // Opt Escape Rule
791 const bool bNot
= SQL_ISTOKEN(pPart2
->getChild(0), NOT
);
793 if (!(pAtom
->getNodeType() == SQLNodeType::String
||
794 pAtom
->getNodeType() == SQLNodeType::Name
||
795 SQL_ISRULE(pAtom
,parameter
) ||
796 ( pAtom
->getChild(0) && pAtom
->getChild(0)->getNodeType() == SQLNodeType::Name
) ||
797 ( pAtom
->getChild(0) && pAtom
->getChild(0)->getNodeType() == SQLNodeType::String
)
800 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_STRING
, *this );
803 OUString sTableRange
;
804 if(SQL_ISRULE(pColumn
,column_ref
))
805 m_pSQLIterator
->getColumnRange(pColumn
,columnName
,sTableRange
);
807 SAL_INFO("connectivity.mork", "ColumnName = " << columnName
);
809 if ( SQL_ISRULE(pAtom
,parameter
) ) {
810 parseParameter( pAtom
, matchString
);
811 // Replace all '*' with '%' : UI Usually does this but not with
812 // Parameters for some reason.
813 matchString
= matchString
.replaceAll( ALT_WILDCARD
, WILDCARD
);
817 matchString
= pAtom
->getTokenValue();
820 // Determine where '%' character is...
822 if ( matchString
== WILDCARD
)
824 // String containing only a '%' and nothing else
825 op
= MQueryOp::Exists
;
826 // Will be ignored for Exists case, but clear anyway.
829 else if ( matchString
.indexOf ( WILDCARD
) == -1 &&
830 matchString
.indexOf ( MATCHCHAR
) == -1 )
832 // Simple string , eg. "to match"
834 op
= MQueryOp::DoesNotContain
;
836 op
= MQueryOp::Contains
;
838 else if ( matchString
.startsWith( WILDCARD
)
839 && matchString
.endsWith( WILDCARD
)
840 && matchString
.indexOf ( WILDCARD
, 1 ) == matchString
.lastIndexOf ( WILDCARD
)
841 && matchString
.indexOf( MATCHCHAR
) == -1
844 // Relatively simple "%string%" - ie, contains...
845 // Cut '%' from front and rear
846 matchString
= matchString
.replaceAt( 0, 1, OUString() );
847 matchString
= matchString
.replaceAt( matchString
.getLength() -1 , 1, OUString() );
850 op
= MQueryOp::DoesNotContain
;
852 op
= MQueryOp::Contains
;
856 // We currently can't handle a 'NOT LIKE' when there are '%' or
857 // '_' dispersed throughout
858 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_NOT_LIKE_TOO_COMPLEX
, *this );
862 if ( (matchString
.indexOf ( WILDCARD
) == matchString
.lastIndexOf ( WILDCARD
))
863 && matchString
.indexOf( MATCHCHAR
) == -1
866 // One occurrence of '%' - no '_' matches...
867 if ( matchString
.startsWith( WILDCARD
) )
869 op
= MQueryOp::EndsWith
;
870 matchString
= matchString
.replaceAt( 0, 1, OUString());
872 else if ( matchString
.indexOf ( WILDCARD
) == matchString
.getLength() -1 )
874 op
= MQueryOp::BeginsWith
;
875 matchString
= matchString
.replaceAt( matchString
.getLength() -1 , 1, OUString() );
879 sal_Int32 pos
= matchString
.indexOf ( WILDCARD
);
880 matchString
= matchString
.replaceAt( pos
, 1, ".*" );
881 op
= MQueryOp::RegExp
;
887 // Most Complex, need to use an RE
889 while ( (pos
= matchString
.indexOf ( WILDCARD
)) != -1 )
891 matchString
= matchString
.replaceAt( pos
, 1, ".*" );
894 while ( (pos
= matchString
.indexOf( MATCHCHAR
)) != -1 )
896 matchString
= matchString
.replaceAt( pos
, 1, "." );
899 op
= MQueryOp::RegExp
;
903 queryExpression
.addExpression( new MQueryExpressionString( columnName
, op
, matchString
));
905 else if (SQL_ISRULE(parseTree
,test_for_null
))
907 OSL_ENSURE(parseTree
->count() == 2,"Error in ParseTree");
908 const OSQLParseNode
* pPart2
= parseTree
->getChild(1);
909 OSL_ENSURE(SQL_ISTOKEN(pPart2
->getChild(0),IS
),"Error in ParseTree");
911 if (!SQL_ISRULE(parseTree
->getChild(0),column_ref
))
913 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_IS_NULL_COLUMN
, *this );
916 if (SQL_ISTOKEN(pPart2
->getChild(1),NOT
))
918 op
= MQueryOp::Exists
;
922 op
= MQueryOp::DoesNotExist
;
925 OUString sTableRange
;
926 m_pSQLIterator
->getColumnRange(parseTree
->getChild(0),columnName
,sTableRange
);
928 queryExpression
.addExpression( new MQueryExpressionString( columnName
, op
));
932 SAL_WARN("connectivity.mork", "Unexpected statement!!!" );
933 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
937 void OResultSet::fillRowData()
939 OSL_ENSURE( m_pStatement
, "Require a statement" );
941 MQueryExpression queryExpression
;
943 OConnection
* pConnection
= static_cast<OConnection
*>(m_pStatement
->getConnection().get());
944 m_xColumns
= m_pSQLIterator
->getSelectColumns();
946 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
948 const OUString sPropertyName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
);
951 for (const auto& rxColumn
: m_xColumns
->get())
953 rxColumn
->getPropertyValue(sPropertyName
) >>= sName
;
955 "connectivity.mork", "Query Columns : (" << i
<< ") " << sName
);
959 // Generate Match Conditions for Query
960 const OSQLParseNode
* pParseTree
= m_pSQLIterator
->getWhereTree();
962 m_bIsAlwaysFalseQuery
= false;
963 if ( pParseTree
!= nullptr )
965 // Extract required info
967 analyseWhereClause( pParseTree
, queryExpression
);
969 // If the query is a 0=1 then set Row count to 0 and return
970 if ( m_bIsAlwaysFalseQuery
)
972 m_bIsReadOnly
= TRISTATE_TRUE
;
976 OUString
aStr( m_xTable
->getName() );
977 m_aQueryHelper
.setAddressbook( aStr
);
979 sal_Int32 rv
= m_aQueryHelper
.executeQuery(pConnection
, queryExpression
);
981 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERR_EXECUTING_QUERY
, *this );
984 if (m_aQueryHelper
.hadError())
986 m_pStatement
->getOwnConnection()->throwSQLException( m_aQueryHelper
.getError(), *this );
989 //determine whether the address book is readonly
992 SAL_INFO("connectivity.mork", "executeQuery returned " << rv
);
996 static bool matchRow( OValueRow
const & row1
, OValueRow
const & row2
)
998 // the first column is the bookmark column
999 return std::equal(std::next(row1
->get().begin()), row1
->get().end(), std::next(row2
->get().begin()),
1000 [](const ORowSetValue
& a
, const ORowSetValue
& b
) { return !a
.isBound() || a
== b
; });
1003 sal_Int32
OResultSet::getRowForCardNumber(sal_Int32 nCardNum
)
1005 SAL_INFO("connectivity.mork", "nCardNum = " << nCardNum
);
1007 if ( m_pKeySet
.is() )
1010 for(nPos
=0;nPos
< static_cast<sal_Int32
>(m_pKeySet
->get().size());nPos
++)
1012 if (nCardNum
== (m_pKeySet
->get())[nPos
])
1014 SAL_INFO("connectivity.mork", "return = " << nPos
+1);
1020 m_pStatement
->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK
, *this );
1025 void OResultSet::executeQuery()
1027 ResultSetEntryGuard
aGuard( *this );
1029 OSL_ENSURE( m_xTable
.is(), "Need a Table object");
1032 const OSQLTables
& rTabs
= m_pSQLIterator
->getTables();
1033 if (rTabs
.empty() || !rTabs
.begin()->second
.is())
1034 m_pStatement
->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX
, *this );
1036 m_xTable
= static_cast< OTable
* > (rTabs
.begin()->second
.get());
1043 OSL_ENSURE(m_xColumns
.is(), "Need the Columns!!");
1045 switch( m_pSQLIterator
->getStatementType() )
1047 case OSQLStatementType::Select
:
1049 if(m_bIsAlwaysFalseQuery
) {
1054 m_pStatement
->getOwnConnection()->throwSQLException( STR_NO_COUNT_SUPPORT
, *this );
1058 bool bDistinct
= false;
1059 OSQLParseNode
*pDistinct
= m_pParseTree
->getChild(1);
1060 if (pDistinct
&& pDistinct
->getTokenID() == SQL_TOKEN_DISTINCT
)
1064 m_aOrderbyColumnNumber
.push_back(m_aColMapping
[1]);
1065 m_aOrderbyAscending
.push_back(TAscendingOrder::DESC
);
1070 OSortIndex::TKeyTypeVector
eKeyType(m_aOrderbyColumnNumber
.size());
1071 std::vector
<sal_Int16
>::size_type index
= 0;
1072 for (const auto& rColIndex
: m_aOrderbyColumnNumber
)
1074 OSL_ENSURE(static_cast<sal_Int32
>(m_aRow
->get().size()) > rColIndex
,"Invalid Index");
1075 switch ((m_aRow
->get().begin()+rColIndex
)->getTypeKind())
1077 case DataType::CHAR
:
1078 case DataType::VARCHAR
:
1079 eKeyType
[index
] = OKeyType::String
;
1082 case DataType::OTHER
:
1083 case DataType::TINYINT
:
1084 case DataType::SMALLINT
:
1085 case DataType::INTEGER
:
1086 case DataType::DECIMAL
:
1087 case DataType::NUMERIC
:
1088 case DataType::REAL
:
1089 case DataType::DOUBLE
:
1090 case DataType::DATE
:
1091 case DataType::TIME
:
1092 case DataType::TIMESTAMP
:
1094 eKeyType
[index
] = OKeyType::Double
;
1097 // Other types aren't implemented (so they are always FALSE)
1099 eKeyType
[index
] = OKeyType::NONE
;
1100 OSL_FAIL("MResultSet::executeQuery: Order By Data Type not implemented");
1108 // Implement Sorting
1110 // So that we can sort we need to wait until the executed
1111 // query to the mozilla addressbooks has returned all
1114 OSortIndex
aSortIndex(eKeyType
,m_aOrderbyAscending
);
1116 #if OSL_DEBUG_LEVEL > 0
1117 for ( std::vector
<sal_Int32
>::size_type i
= 0; i
< m_aColMapping
.size(); i
++ )
1119 "connectivity.mork",
1120 "Mapped: " << i
<< " -> " << m_aColMapping
[i
]);
1122 for ( sal_Int32 nRow
= 1; nRow
<= m_aQueryHelper
.getResultCount(); nRow
++ ) {
1124 std::unique_ptr
<OKeyValue
> pKeyValue
= OKeyValue::createKeyValue(nRow
);
1126 for (const auto& rColIndex
: m_aOrderbyColumnNumber
)
1128 const ORowSetValue
& value
= getValue(nRow
, rColIndex
);
1131 "connectivity.mork",
1132 "Adding Value: (" << nRow
<< "," << rColIndex
1133 << ") : " << value
.getString());
1135 pKeyValue
->pushKey(new ORowSetValueDecorator(value
));
1138 aSortIndex
.AddKeyValue( std::move(pKeyValue
) );
1141 m_pKeySet
= aSortIndex
.CreateKeySet();
1142 m_CurrentRowCount
= static_cast<sal_Int32
>(m_pKeySet
->get().size());
1143 #if OSL_DEBUG_LEVEL > 0
1144 for( OKeySet::Vector::size_type i
= 0; i
< m_pKeySet
->get().size(); i
++ )
1146 "connectivity.mork",
1147 "Sorted: " << i
<< " -> " << (m_pKeySet
->get())[i
]);
1150 beforeFirst(); // Go back to start
1152 else //we always need m_pKeySet now
1153 m_pKeySet
= new OKeySet();
1155 // Handle the DISTINCT case
1156 if ( bDistinct
&& m_pKeySet
.is() )
1158 OValueRow aSearchRow
= new OValueVector( m_aRow
->get().size() );
1160 for(sal_Int32
& i
: m_pKeySet
->get())
1162 fetchRow( i
); // Fills m_aRow
1163 if ( matchRow( m_aRow
, aSearchRow
) )
1165 i
= 0; // Marker for later to be removed
1169 // They don't match, so it's not a duplicate.
1170 // Use the current Row as the next one to match against
1171 *aSearchRow
= *m_aRow
;
1174 // Now remove any keys marked with a 0
1175 m_pKeySet
->get().erase(std::remove_if(m_pKeySet
->get().begin(),m_pKeySet
->get().end()
1176 ,[](sal_Int32 n
) { return n
== 0; })
1177 ,m_pKeySet
->get().end());
1183 case OSQLStatementType::Update
:
1184 case OSQLStatementType::Delete
:
1185 case OSQLStatementType::Insert
:
1188 m_pStatement
->getOwnConnection()->throwSQLException( STR_STMT_TYPE_NOT_SUPPORTED
, *this );
1193 void OResultSet::setBoundedColumns(const OValueRow
& _rRow
,
1194 const ::rtl::Reference
<connectivity::OSQLColumns
>& _rxColumns
,
1195 const Reference
<XIndexAccess
>& _xNames
,
1196 bool _bSetColumnMapping
,
1197 const Reference
<XDatabaseMetaData
>& _xMetaData
,
1198 std::vector
<sal_Int32
>& _rColMapping
)
1200 ::comphelper::UStringMixEqual
aCase(_xMetaData
->supportsMixedCaseQuotedIdentifiers());
1202 Reference
<XPropertySet
> xTableColumn
;
1203 OUString sTableColumnName
, sSelectColumnRealName
;
1205 const OUString sName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
);
1206 const OUString sRealName
= OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME
);
1208 std::vector
< OUString
> aColumnNames
;
1209 aColumnNames
.reserve(_rxColumns
->get().size());
1210 OValueVector::Vector::iterator aRowIter
= _rRow
->get().begin()+1;
1211 for (sal_Int32 i
=0; // the first column is the bookmark column
1212 aRowIter
!= _rRow
->get().end();
1218 // get the table column and its name
1219 _xNames
->getByIndex(i
) >>= xTableColumn
;
1220 OSL_ENSURE(xTableColumn
.is(), "OResultSet::setBoundedColumns: invalid table column!");
1221 if (xTableColumn
.is())
1222 xTableColumn
->getPropertyValue(sName
) >>= sTableColumnName
;
1224 sTableColumnName
.clear();
1226 // look if we have such a select column
1227 // TODO: would like to have a O(log n) search here ...
1228 sal_Int32 nColumnPos
= 0;
1229 for (const auto& rxColumn
: _rxColumns
->get())
1231 if ( nColumnPos
< static_cast<sal_Int32
>(aColumnNames
.size()) )
1232 sSelectColumnRealName
= aColumnNames
[nColumnPos
];
1235 if(rxColumn
->getPropertySetInfo()->hasPropertyByName(sRealName
))
1236 rxColumn
->getPropertyValue(sRealName
) >>= sSelectColumnRealName
;
1238 rxColumn
->getPropertyValue(sName
) >>= sSelectColumnRealName
;
1239 aColumnNames
.push_back(sSelectColumnRealName
);
1242 if (aCase(sTableColumnName
, sSelectColumnRealName
))
1244 if(_bSetColumnMapping
)
1246 sal_Int32 nSelectColumnPos
= nColumnPos
+ 1;
1247 // the getXXX methods are 1-based ...
1248 sal_Int32 nTableColumnPos
= i
+ 1;
1249 // get first table column is the bookmark column
1252 "connectivity.mork",
1253 "Set Col Mapping: " << nSelectColumnPos
<< " -> "
1254 << nTableColumnPos
);
1255 _rColMapping
[nSelectColumnPos
] = nTableColumnPos
;
1258 aRowIter
->setBound(true);
1259 aRowIter
->setTypeKind(DataType::VARCHAR
);
1267 OSL_FAIL("OResultSet::setBoundedColumns: caught an Exception!");
1273 bool OResultSet::isCount() const
1275 return (m_pParseTree
&&
1276 m_pParseTree
->count() > 2 &&
1277 SQL_ISRULE(m_pParseTree
->getChild(2),scalar_exp_commalist
) &&
1278 SQL_ISRULE(m_pParseTree
->getChild(2)->getChild(0),derived_column
) &&
1279 SQL_ISRULE(m_pParseTree
->getChild(2)->getChild(0)->getChild(0),general_set_fct
) &&
1280 m_pParseTree
->getChild(2)->getChild(0)->getChild(0)->count() == 4
1285 // Check for valid row in m_aQuery
1287 bool OResultSet::validRow( sal_uInt32 nRow
)
1289 sal_Int32 nNumberOfRecords
= m_aQueryHelper
.getResultCount();
1291 if (( nRow
== 0 ) ||
1292 ( nRow
> static_cast<sal_uInt32
>(nNumberOfRecords
)) ){
1293 SAL_INFO("connectivity.mork", "validRow(" << nRow
<< "): return False");
1296 SAL_INFO("connectivity.mork", "validRow(" << nRow
<< "): return True");
1301 void OResultSet::fillKeySet(sal_Int32 nMaxCardNumber
)
1303 impl_ensureKeySet();
1304 if (m_CurrentRowCount
< nMaxCardNumber
)
1306 sal_Int32 nKeyValue
;
1307 if ( static_cast<sal_Int32
>(m_pKeySet
->get().capacity()) < nMaxCardNumber
)
1308 m_pKeySet
->get().reserve(nMaxCardNumber
+ 20 );
1310 for (nKeyValue
= m_CurrentRowCount
+1; nKeyValue
<= nMaxCardNumber
; nKeyValue
++)
1311 m_pKeySet
->get().push_back( nKeyValue
);
1312 m_CurrentRowCount
= nMaxCardNumber
;
1316 sal_Int32
OResultSet::deletedCount()
1318 impl_ensureKeySet();
1319 return m_CurrentRowCount
- static_cast<sal_Int32
>(m_pKeySet
->get().size());
1323 bool OResultSet::seekRow( eRowPosition pos
, sal_Int32 nOffset
)
1325 ResultSetEntryGuard
aGuard( *this );
1326 if ( !m_pKeySet
.is() )
1327 m_pStatement
->getOwnConnection()->throwSQLException( STR_ILLEGAL_MOVEMENT
, *this );
1329 sal_Int32 nNumberOfRecords
= m_aQueryHelper
.getResultCount();
1330 sal_Int32 nRetrievedRows
= currentRowCount();
1331 sal_Int32 nCurPos
= m_nRowPos
;
1333 SAL_INFO("connectivity.mork", "nCurPos = " << nCurPos
);
1346 nCurPos
= nRetrievedRows
;
1352 nCurPos
+= sal_uInt32( nOffset
);
1356 if ( nCurPos
<= 0 ) {
1359 "connectivity.mork", "return False, m_nRowPos = " << m_nRowPos
);
1363 if ( nCurPos
< static_cast<sal_Int32
>(m_pKeySet
->get().size()) ) //The requested row is exist in m_pKeySet, so we just use it
1365 nCurCard
= (m_pKeySet
->get())[nCurPos
-1];
1367 else //The requested row has not been retrieved until now. We should get the right card for it.
1368 nCurCard
= nCurPos
+ deletedCount();
1370 if ( nCurCard
> nNumberOfRecords
) {
1371 fillKeySet(nNumberOfRecords
);
1372 m_nRowPos
= static_cast<sal_uInt32
>(m_pKeySet
->get().size() + 1);
1374 "connectivity.mork", "return False, m_nRowPos = " << m_nRowPos
);
1377 //Insert new retrieved items for later use
1378 fillKeySet(nNumberOfRecords
);
1379 m_nRowPos
= static_cast<sal_uInt32
>(nCurPos
);
1380 SAL_INFO("connectivity.mork", "return True, m_nRowPos = " << m_nRowPos
);
1385 void OResultSet::setColumnMapping(const std::vector
<sal_Int32
>& _aColumnMapping
)
1387 m_aColMapping
= _aColumnMapping
;
1388 #if OSL_DEBUG_LEVEL > 0
1389 for ( size_t i
= 0; i
< m_aColMapping
.size(); i
++ )
1391 "connectivity.mork",
1392 "Set Mapped: " << i
<< " -> " << m_aColMapping
[i
]);
1397 css::uno::Any
OResultSet::getBookmark( )
1399 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1400 ResultSetEntryGuard
aGuard( *this );
1401 if ( !fetchCurrentRow() ) {
1402 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1405 OSL_ENSURE((!m_aRow
->isDeleted()),"getBookmark called for deleted row");
1406 return makeAny(static_cast<sal_Int32
>((m_aRow
->get())[0]));
1408 sal_Bool
OResultSet::moveToBookmark( const css::uno::Any
& bookmark
)
1410 ResultSetEntryGuard
aGuard( *this );
1412 "connectivity.mork", "bookmark = " << comphelper::getINT32(bookmark
));
1413 sal_Int32 nCardNum
= comphelper::getINT32(bookmark
);
1414 m_nRowPos
= getRowForCardNumber(nCardNum
);
1418 sal_Bool
OResultSet::moveRelativeToBookmark( const css::uno::Any
& bookmark
, sal_Int32 rows
)
1420 ResultSetEntryGuard
aGuard( *this );
1422 "connectivity.mork",
1423 "bookmark = " << comphelper::getINT32(bookmark
) << " rows= " << rows
);
1424 sal_Int32 nCardNum
= comphelper::getINT32(bookmark
);
1425 m_nRowPos
= getRowForCardNumber(nCardNum
);
1426 return seekRow(RELATIVE_POS
,rows
);
1428 sal_Int32
OResultSet::compareBookmarks( const css::uno::Any
& lhs
, const css::uno::Any
& rhs
)
1430 ResultSetEntryGuard
aGuard( *this );
1431 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1433 sal_Int32 nSecond
=0;
1434 sal_Int32 nResult
=0;
1436 if ( !( lhs
>>= nFirst
) || !( rhs
>>= nSecond
) ) {
1437 m_pStatement
->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK
, *this );
1440 if(nFirst
< nSecond
)
1441 nResult
= CompareBookmark::LESS
;
1442 else if(nFirst
> nSecond
)
1443 nResult
= CompareBookmark::GREATER
;
1445 nResult
= CompareBookmark::EQUAL
;
1449 sal_Bool
OResultSet::hasOrderedBookmarks( )
1451 ResultSetEntryGuard
aGuard( *this );
1452 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1455 sal_Int32
OResultSet::hashBookmark( const css::uno::Any
& bookmark
)
1457 ResultSetEntryGuard
aGuard( *this );
1458 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1459 return comphelper::getINT32(bookmark
);
1462 sal_Int32
OResultSet::getCurrentCardNumber()
1464 if ( ( m_nRowPos
== 0 ) || !m_pKeySet
.is() )
1466 if (m_pKeySet
->get().size() < m_nRowPos
)
1468 return (m_pKeySet
->get())[m_nRowPos
-1];
1470 void OResultSet::checkPendingUpdate()
1472 OSL_FAIL( "OResultSet::checkPendingUpdate() not implemented" );
1474 const sal_Int32 nCurrentRow = getCurrentCardNumber();
1476 if ((m_nNewRow && nCurrentRow != m_nNewRow)
1477 || ( m_nUpdatedRow && m_nUpdatedRow != nCurrentRow))
1479 const OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1481 "$position$", OUString::valueOf(nCurrentRow)
1483 ::dbtools::throwGenericSQLException(sError,*this);
1488 void OResultSet::updateValue(sal_Int32 columnIndex
,const ORowSetValue
& x
)
1490 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1491 ResultSetEntryGuard
aGuard( *this );
1492 if ( !fetchCurrentRow() ) {
1493 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1496 checkPendingUpdate();
1498 checkIndex(columnIndex
);
1499 columnIndex
= mapColumn(columnIndex
);
1501 (m_aRow
->get())[columnIndex
].setBound(true);
1502 (m_aRow
->get())[columnIndex
] = x
;
1506 void SAL_CALL
OResultSet::updateNull( sal_Int32 columnIndex
)
1508 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1509 ResultSetEntryGuard
aGuard( *this );
1510 if ( !fetchCurrentRow() )
1511 m_pStatement
->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW
, *this );
1513 checkPendingUpdate();
1514 checkIndex(columnIndex
);
1515 columnIndex
= mapColumn(columnIndex
);
1517 (m_aRow
->get())[columnIndex
].setBound(true);
1518 (m_aRow
->get())[columnIndex
].setNull();
1522 void SAL_CALL
OResultSet::updateBoolean( sal_Int32 columnIndex
, sal_Bool x
)
1524 updateValue(columnIndex
, static_cast<bool>(x
));
1527 void SAL_CALL
OResultSet::updateByte( sal_Int32 columnIndex
, sal_Int8 x
)
1529 updateValue(columnIndex
,x
);
1533 void SAL_CALL
OResultSet::updateShort( sal_Int32 columnIndex
, sal_Int16 x
)
1535 updateValue(columnIndex
,x
);
1538 void SAL_CALL
OResultSet::updateInt( sal_Int32 columnIndex
, sal_Int32 x
)
1540 updateValue(columnIndex
,x
);
1543 void SAL_CALL
OResultSet::updateLong( sal_Int32
/*columnIndex*/, sal_Int64
/*x*/ )
1545 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::updateLong", *this );
1548 void SAL_CALL
OResultSet::updateFloat( sal_Int32 columnIndex
, float x
)
1550 updateValue(columnIndex
,x
);
1554 void SAL_CALL
OResultSet::updateDouble( sal_Int32 columnIndex
, double x
)
1556 updateValue(columnIndex
,x
);
1559 void SAL_CALL
OResultSet::updateString( sal_Int32 columnIndex
, const OUString
& x
)
1561 updateValue(columnIndex
,x
);
1564 void SAL_CALL
OResultSet::updateBytes( sal_Int32 columnIndex
, const Sequence
< sal_Int8
>& x
)
1566 updateValue(columnIndex
,x
);
1569 void SAL_CALL
OResultSet::updateDate( sal_Int32 columnIndex
, const css::util::Date
& x
)
1571 updateValue(columnIndex
,x
);
1575 void SAL_CALL
OResultSet::updateTime( sal_Int32 columnIndex
, const css::util::Time
& x
)
1577 updateValue(columnIndex
,x
);
1581 void SAL_CALL
OResultSet::updateTimestamp( sal_Int32 columnIndex
, const css::util::DateTime
& x
)
1583 updateValue(columnIndex
,x
);
1587 void SAL_CALL
OResultSet::updateBinaryStream( sal_Int32 columnIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
1589 ResultSetEntryGuard
aGuard( *this );
1592 ::dbtools::throwFunctionSequenceException(*this);
1594 Sequence
<sal_Int8
> aSeq
;
1595 x
->readBytes(aSeq
,length
);
1596 updateValue(columnIndex
,aSeq
);
1599 void SAL_CALL
OResultSet::updateCharacterStream( sal_Int32 columnIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
1601 updateBinaryStream(columnIndex
,x
,length
);
1604 void SAL_CALL
OResultSet::updateObject( sal_Int32 columnIndex
, const Any
& x
)
1606 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1608 const OUString
sError( m_pStatement
->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1609 STR_COLUMN_NOT_UPDATEABLE
,
1610 "$position$", OUString::number(columnIndex
)
1612 ::dbtools::throwGenericSQLException(sError
,*this);
1613 } // if (!::dbtools::implUpdateObject(this, columnIndex, x))
1617 void SAL_CALL
OResultSet::updateNumericObject( sal_Int32 columnIndex
, const Any
& x
, sal_Int32
/*scale*/ )
1619 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1621 const OUString
sError( m_pStatement
->getOwnConnection()->getResources().getResourceStringWithSubstitution(
1622 STR_COLUMN_NOT_UPDATEABLE
,
1623 "$position$", OUString::number(columnIndex
)
1625 ::dbtools::throwGenericSQLException(sError
,*this);
1631 void SAL_CALL
OResultSet::insertRow( )
1633 ResultSetEntryGuard
aGuard( *this );
1634 SAL_INFO("connectivity.mork", "in, m_nRowPos = " << m_nRowPos
);
1635 // m_RowStates = RowStates_Inserted;
1637 //m_aQueryHelper.setRowStates(getCurrentCardNumber(),m_RowStates);
1638 SAL_INFO("connectivity.mork", "out, m_nRowPos = " << m_nRowPos
);
1641 void SAL_CALL
OResultSet::updateRow( )
1643 OSL_FAIL( "OResultSet::updateRow( ) not implemented" );
1646 void SAL_CALL
OResultSet::deleteRow( )
1648 OSL_FAIL( "OResultSet::deleteRow( ) not implemented" );
1651 void SAL_CALL
OResultSet::cancelRowUpdates( )
1653 OSL_FAIL( "OResultSet::cancelRowUpdates( ) not implemented" );
1656 void SAL_CALL
OResultSet::moveToInsertRow( )
1658 OSL_FAIL( "OResultSet::moveToInsertRow( ) not implemented" );
1661 void SAL_CALL
OResultSet::moveToCurrentRow( )
1663 ResultSetEntryGuard
aGuard( *this );
1664 SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos
);
1672 bool OResultSet::determineReadOnly()
1674 // OSL_FAIL( "OResultSet::determineReadOnly( ) not implemented" );
1676 if (m_bIsReadOnly
== TRISTATE_INDET
)
1678 m_bIsReadOnly
= TRISTATE_TRUE
;
1679 // OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
1680 // m_bIsReadOnly = !m_aQueryHelper.isWritable(xConnection) || m_bIsAlwaysFalseQuery;
1683 return m_bIsReadOnly
!= TRISTATE_FALSE
;
1686 void OResultSet::setTable(OTable
* _rTable
)
1689 m_xTableColumns
= m_xTable
->getColumns();
1690 if(m_xTableColumns
.is())
1691 m_aColumnNames
= m_xTableColumns
->getElementNames();
1694 void OResultSet::setOrderByColumns(const std::vector
<sal_Int32
>& _aColumnOrderBy
)
1696 m_aOrderbyColumnNumber
= _aColumnOrderBy
;
1699 void OResultSet::setOrderByAscending(const std::vector
<TAscendingOrder
>& _aOrderbyAsc
)
1701 m_aOrderbyAscending
= _aOrderbyAsc
;
1703 Sequence
< sal_Int32
> SAL_CALL
OResultSet::deleteRows( const Sequence
< Any
>& /*rows*/ )
1705 ::dbtools::throwFeatureNotImplementedSQLException( "XDeleteRows::deleteRows", *this );
1706 return Sequence
< sal_Int32
>();
1709 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */