1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * Effective License of whole file:
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
22 * The Contents of this file are made available subject to the terms of
23 * the GNU Lesser General Public License Version 2.1
25 * Copyright: 2000 by Sun Microsystems, Inc.
27 * Contributor(s): Joerg Budischewski
29 * All parts contributed on or after August 2011:
31 * This Source Code Form is subject to the terms of the Mozilla Public
32 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
35 ************************************************************************/
37 #include <osl/thread.h>
39 #include <rtl/ustrbuf.hxx>
41 #include <cppuhelper/typeprovider.hxx>
42 #include <cppuhelper/queryinterface.hxx>
44 #include "pq_tools.hxx"
45 #include "pq_array.hxx"
46 #include "pq_statement.hxx"
47 #include "pq_baseresultset.hxx"
48 #include "pq_resultsetmetadata.hxx"
50 #include <com/sun/star/lang/DisposedException.hpp>
52 #include <connectivity/dbconversion.hxx>
55 using osl::MutexGuard
;
58 using com::sun::star::beans::XPropertySetInfo
;
59 using com::sun::star::beans::XPropertySet
;
60 using com::sun::star::beans::XMultiPropertySet
;
61 using com::sun::star::beans::XFastPropertySet
;
63 using com::sun::star::uno::Any
;
64 using com::sun::star::uno::makeAny
;
65 using com::sun::star::uno::Type
;
66 using com::sun::star::uno::RuntimeException
;
67 using com::sun::star::uno::Exception
;
68 using com::sun::star::uno::Sequence
;
69 using com::sun::star::uno::Reference
;
70 using com::sun::star::uno::XInterface
;
72 using com::sun::star::lang::IllegalArgumentException
;
74 using com::sun::star::sdbc::XWarningsSupplier
;
75 using com::sun::star::sdbc::XCloseable
;
76 using com::sun::star::sdbc::XStatement
;
77 using com::sun::star::sdbc::XResultSet
;
78 using com::sun::star::sdbc::XConnection
;
79 using com::sun::star::sdbc::SQLException
;
80 using com::sun::star::sdbc::XRow
;
81 using com::sun::star::sdbc::XColumnLocate
;
82 using com::sun::star::sdbc::XResultSetMetaData
;
83 using com::sun::star::sdbc::XResultSetMetaDataSupplier
;
86 using com::sun::star::beans::Property
;
88 using namespace dbtools
;
90 namespace pq_sdbc_driver
92 static ::cppu::IPropertyArrayHelper
& getResultSetPropertyArrayHelper()
94 static ::cppu::IPropertyArrayHelper
*pArrayHelper
;
97 MutexGuard
guard( Mutex::getGlobalMutex() );
100 static Property aTable
[] =
102 // LEM TODO: this needs to be kept in sync with other, e.g. pq_statics.css:508
103 // Should really share!
104 // At least use for the handles the #define'd values in .hxx file...
106 OUString("CursorName"), 0,
107 ::cppu::UnoType
<OUString
>::get() , 0 ),
109 OUString("EscapeProcessing"), 1,
110 ::getBooleanCppuType() , 0 ),
112 OUString("FetchDirection"), 2,
113 ::cppu::UnoType
<sal_Int32
>::get() , 0 ),
115 OUString("FetchSize"), 3,
116 ::cppu::UnoType
<sal_Int32
>::get() , 0 ),
118 OUString("IsBookmarkable"), 4,
119 ::getBooleanCppuType() , 0 ),
121 OUString("ResultSetConcurrency"), 5,
122 ::cppu::UnoType
<sal_Int32
>::get() , 0 ),
124 OUString("ResultSetType"), 6,
125 ::cppu::UnoType
<sal_Int32
>::get() , 0 )
127 OSL_ASSERT( sizeof(aTable
) / sizeof(Property
) == BASERESULTSET_SIZE
);
128 static ::cppu::OPropertyArrayHelper
arrayHelper( aTable
, BASERESULTSET_SIZE
, sal_True
);
129 pArrayHelper
= &arrayHelper
;
132 return *pArrayHelper
;
135 BaseResultSet::BaseResultSet(
136 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
137 const Reference
< XInterface
> & owner
,
140 const Reference
< com::sun::star::script::XTypeConverter
> & tc
)
141 : OComponentHelper( refMutex
->mutex
)
142 , OPropertySetHelper( OComponentHelper::rBHelper
)
145 , m_refMutex( refMutex
)
147 , m_rowCount( rowCount
)
148 , m_fieldCount( colCount
)
151 POSTGRE_TRACE( "ctor BaseResultSet" );
154 // LEM TODO: refMutex->mutex should live longer than OComponentHelper,
155 // but calling OComponentHelper::dispose explicitly here calls
156 // BaseResultSet::~BaseResultSet in an infinite loop :(
157 BaseResultSet::~BaseResultSet()
159 POSTGRE_TRACE( "dtor BaseResultSet" );
162 Any
BaseResultSet::queryInterface( const Type
& reqType
) throw (RuntimeException
, std::exception
)
166 ret
= OComponentHelper::queryInterface( reqType
);
167 if( ! ret
.hasValue() )
168 ret
= ::cppu::queryInterface( reqType
,
169 static_cast< XResultSet
* > ( this ),
170 static_cast< XResultSetMetaDataSupplier
* > ( this ),
171 static_cast< XRow
* > ( this ),
172 static_cast< XColumnLocate
* > ( this ),
173 static_cast< XCloseable
* > ( this ),
174 static_cast< XPropertySet
* > ( this ),
175 static_cast< XMultiPropertySet
* > ( this ),
176 static_cast< XFastPropertySet
* > ( this ) );
180 // void BaseResultSet::close( ) throw (SQLException, RuntimeException)
182 // Reference< XInterface > owner;
184 // ResultSetGuard guard(*this);
187 // PQclear(m_result );
196 Sequence
<Type
> BaseResultSet::getTypes() throw( RuntimeException
, std::exception
)
198 static cppu::OTypeCollection
*pCollection
;
201 MutexGuard
guard( osl::Mutex::getGlobalMutex() );
204 static cppu::OTypeCollection
collection(
205 getCppuType( (Reference
< XResultSet
> *) 0 ),
206 getCppuType( (Reference
< XResultSetMetaDataSupplier
> *) 0 ),
207 getCppuType( (Reference
< XRow
> *) 0 ),
208 getCppuType( (Reference
< XColumnLocate
> *) 0 ),
209 getCppuType( (Reference
< XCloseable
> *) 0 ),
210 getCppuType( (Reference
< XPropertySet
>*) 0 ),
211 getCppuType( (Reference
< XFastPropertySet
> *) 0 ),
212 getCppuType( (Reference
< XMultiPropertySet
> *) 0 ),
213 OComponentHelper::getTypes());
214 pCollection
= &collection
;
217 return pCollection
->getTypes();
220 Sequence
< sal_Int8
> BaseResultSet::getImplementationId() throw( RuntimeException
, std::exception
)
222 return css::uno::Sequence
<sal_Int8
>();
225 // Reference< XResultSetMetaData > BaseResultSet::getMetaData( ) throw (SQLException, RuntimeException)
227 // ResultSetGuard guard(*this);
229 // return new ResultSetMetaData( m_refMutex, this, &m_result );
232 sal_Bool
BaseResultSet::next( ) throw (SQLException
, RuntimeException
, std::exception
)
234 MutexGuard
guard( m_refMutex
->mutex
);
237 return m_row
< m_rowCount
;
240 sal_Bool
BaseResultSet::isBeforeFirst( ) throw (SQLException
, RuntimeException
, std::exception
)
242 MutexGuard
guard( m_refMutex
->mutex
);
247 sal_Bool
BaseResultSet::isAfterLast( ) throw (SQLException
, RuntimeException
, std::exception
)
249 MutexGuard
guard( m_refMutex
->mutex
);
251 return m_row
>= m_rowCount
;
254 sal_Bool
BaseResultSet::isFirst( ) throw (SQLException
, RuntimeException
, std::exception
)
256 MutexGuard
guard( m_refMutex
->mutex
);
258 return m_row
== 0 && m_rowCount
;
261 sal_Bool
BaseResultSet::isLast( ) throw (SQLException
, RuntimeException
, std::exception
)
263 MutexGuard
guard( m_refMutex
->mutex
);
265 return m_row
>= 0 && m_row
+ 1 == m_rowCount
;
268 void BaseResultSet::beforeFirst( ) throw (SQLException
, RuntimeException
, std::exception
)
270 MutexGuard
guard( m_refMutex
->mutex
);
275 void BaseResultSet::afterLast( ) throw (SQLException
, RuntimeException
, std::exception
)
277 MutexGuard
guard( m_refMutex
->mutex
);
282 sal_Bool
BaseResultSet::first( ) throw (SQLException
, RuntimeException
, std::exception
)
284 MutexGuard
guard( m_refMutex
->mutex
);
286 bool bRet
= ( m_rowCount
> 0 );
292 sal_Bool
BaseResultSet::last( ) throw (SQLException
, RuntimeException
, std::exception
)
294 MutexGuard
guard( m_refMutex
->mutex
);
296 bool bRet
= ( m_rowCount
> 0 );
298 m_row
= m_rowCount
-1;
302 sal_Int32
BaseResultSet::getRow( ) throw (SQLException
, RuntimeException
, std::exception
)
304 MutexGuard
guard( m_refMutex
->mutex
);
309 sal_Bool
BaseResultSet::absolute( sal_Int32 row
) throw (SQLException
, RuntimeException
, std::exception
)
311 MutexGuard
guard( m_refMutex
->mutex
);
316 if( m_row
> m_rowCount
)
321 m_row
= m_rowCount
+ row
;
328 sal_Bool
BaseResultSet::relative( sal_Int32 rows
) throw (SQLException
, RuntimeException
, std::exception
)
330 MutexGuard
guard( m_refMutex
->mutex
);
334 if( m_row
> m_rowCount
)
336 else if ( m_row
< -1 )
341 sal_Bool
BaseResultSet::previous( ) throw (SQLException
, RuntimeException
, std::exception
)
343 MutexGuard
guard( m_refMutex
->mutex
);
345 bool bRet
= ( m_row
!= -1 );
351 void BaseResultSet::refreshRow( ) throw (SQLException
, RuntimeException
, std::exception
)
353 // TODO: not supported for now
356 sal_Bool
BaseResultSet::rowUpdated( ) throw (SQLException
, RuntimeException
, std::exception
)
361 sal_Bool
BaseResultSet::rowInserted( ) throw (SQLException
, RuntimeException
, std::exception
)
366 sal_Bool
BaseResultSet::rowDeleted( ) throw (SQLException
, RuntimeException
, std::exception
)
371 Reference
< XInterface
> BaseResultSet::getStatement() throw (SQLException
, RuntimeException
, std::exception
)
373 MutexGuard
guard( m_refMutex
->mutex
);
379 //----------------- XRow interface ----------------------------------------------------
381 sal_Bool
BaseResultSet::wasNull( ) throw (SQLException
, RuntimeException
, std::exception
)
386 Any
BaseResultSet::convertTo( const Any
& val
, const Type
& type
)
391 aRet
= m_tc
->convertTo( val
, type
);
393 catch( com::sun::star::lang::IllegalArgumentException
& )
395 catch( com::sun::star::script::CannotConvertException
& )
400 sal_Bool
BaseResultSet::getBoolean( sal_Int32 columnIndex
) throw (SQLException
, RuntimeException
, std::exception
)
402 MutexGuard
guard( m_refMutex
->mutex
);
404 checkColumnIndex( columnIndex
);
405 checkRowIndex( sal_True
/* must be on row */ );
407 OUString str
= getString( columnIndex
);
409 if( str
.getLength() > 0 )
425 sal_Int8
BaseResultSet::getByte( sal_Int32 columnIndex
)
426 throw (SQLException
, RuntimeException
, std::exception
)
428 MutexGuard
guard( m_refMutex
->mutex
);
430 checkColumnIndex( columnIndex
);
431 checkRowIndex( sal_True
/* must be on row */ );
433 convertTo( getValue( columnIndex
), getCppuType( &b
)) >>= b
;
437 sal_Int16
BaseResultSet::getShort( sal_Int32 columnIndex
)
438 throw (SQLException
, RuntimeException
, std::exception
)
440 MutexGuard
guard( m_refMutex
->mutex
);
442 checkColumnIndex( columnIndex
);
443 checkRowIndex( sal_True
/* must be on row */ );
445 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
449 OUString
BaseResultSet::getString( sal_Int32 columnIndex
) throw (SQLException
, RuntimeException
, std::exception
)
451 MutexGuard
guard(m_refMutex
->mutex
);
453 checkColumnIndex( columnIndex
);
454 checkRowIndex( sal_True
/* must be on row */ );
456 convertTo( getValue( columnIndex
), getCppuType( &ret
) ) >>= ret
;
457 // printf( "BaseResultSet::getString() %s\n" , OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ).getStr() );
461 sal_Int32
BaseResultSet::getInt( sal_Int32 columnIndex
)
462 throw (SQLException
, RuntimeException
, std::exception
)
464 MutexGuard
guard( m_refMutex
->mutex
);
466 checkColumnIndex( columnIndex
);
467 checkRowIndex( sal_True
/* must be on row */ );
469 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
473 sal_Int64
BaseResultSet::getLong( sal_Int32 columnIndex
)
474 throw (SQLException
, RuntimeException
, std::exception
)
476 MutexGuard
guard( m_refMutex
->mutex
);
478 checkColumnIndex( columnIndex
);
479 checkRowIndex( sal_True
/* must be on row */ );
481 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
485 float BaseResultSet::getFloat( sal_Int32 columnIndex
)
486 throw (SQLException
, RuntimeException
, std::exception
)
488 MutexGuard
guard( m_refMutex
->mutex
);
490 checkColumnIndex( columnIndex
);
491 checkRowIndex( sal_True
/* must be on row */ );
493 convertTo( getValue( columnIndex
), getCppuType( &f
)) >>= f
;
497 double BaseResultSet::getDouble( sal_Int32 columnIndex
)
498 throw (SQLException
, RuntimeException
, std::exception
)
500 MutexGuard
guard( m_refMutex
->mutex
);
502 checkColumnIndex( columnIndex
);
504 convertTo( getValue( columnIndex
), getCppuType( &d
)) >>= d
;
508 Sequence
< sal_Int8
> BaseResultSet::getBytes( sal_Int32 columnIndex
)
509 throw (SQLException
, RuntimeException
, std::exception
)
511 MutexGuard
guard( m_refMutex
->mutex
);
513 checkColumnIndex( columnIndex
);
514 checkRowIndex( sal_True
/* must be on row */ );
516 Sequence
< sal_Int8
> ret
;
518 if( ! (getValue( columnIndex
) >>= ustr
) )
522 // if this is a binary, it must contain escaped data !
523 OString val
= OUStringToOString( ustr
, RTL_TEXTENCODING_ASCII_US
);
526 char * res
= (char*) PQunescapeBytea( (unsigned char *)val
.getStr() , &length
);
527 ret
= Sequence
< sal_Int8
> ( (sal_Int8
*)res
, length
);
535 ::com::sun::star::util::Date
BaseResultSet::getDate( sal_Int32 columnIndex
)
536 throw (SQLException
, RuntimeException
, std::exception
)
538 return DBTypeConversion::toDate( getString( columnIndex
) );
541 ::com::sun::star::util::Time
BaseResultSet::getTime( sal_Int32 columnIndex
)
542 throw (SQLException
, RuntimeException
, std::exception
)
544 return DBTypeConversion::toTime( getString( columnIndex
) );
547 ::com::sun::star::util::DateTime
BaseResultSet::getTimestamp( sal_Int32 columnIndex
)
548 throw (SQLException
, RuntimeException
, std::exception
)
550 return DBTypeConversion::toDateTime( getString( columnIndex
) );
553 // LEM TODO: these look like they are missing an actual implementation
554 Reference
< ::com::sun::star::io::XInputStream
> BaseResultSet::getBinaryStream( sal_Int32
/* columnIndex */ )
555 throw (SQLException
, RuntimeException
, std::exception
)
560 Reference
< ::com::sun::star::io::XInputStream
> BaseResultSet::getCharacterStream( sal_Int32
/* columnIndex */ )
561 throw (SQLException
, RuntimeException
, std::exception
)
566 Any
BaseResultSet::getObject(
567 sal_Int32
/* columnIndex */,
568 const Reference
< ::com::sun::star::container::XNameAccess
>& /* typeMap */ )
569 throw (SQLException
, RuntimeException
, std::exception
)
574 Reference
< ::com::sun::star::sdbc::XRef
> BaseResultSet::getRef( sal_Int32
/* columnIndex */ )
575 throw (SQLException
, RuntimeException
, std::exception
)
577 return Reference
< com::sun::star::sdbc::XRef
> ();
580 Reference
< ::com::sun::star::sdbc::XBlob
> BaseResultSet::getBlob( sal_Int32
/* columnIndex */ )
581 throw (SQLException
, RuntimeException
, std::exception
)
583 return Reference
< com::sun::star::sdbc::XBlob
> ();
586 Reference
< ::com::sun::star::sdbc::XClob
> BaseResultSet::getClob( sal_Int32
/* columnIndex */ )
587 throw (SQLException
, RuntimeException
, std::exception
)
589 return Reference
< com::sun::star::sdbc::XClob
> ();
592 Reference
< ::com::sun::star::sdbc::XArray
> BaseResultSet::getArray( sal_Int32 columnIndex
)
593 throw (SQLException
, RuntimeException
, std::exception
)
595 return new Array( m_refMutex
, parseArray( getString( columnIndex
) ), *this, m_tc
);
598 ::cppu::IPropertyArrayHelper
& BaseResultSet::getInfoHelper()
600 return getResultSetPropertyArrayHelper();
603 sal_Bool
BaseResultSet::convertFastPropertyValue(
604 Any
& /* rConvertedValue */, Any
& /* rOldValue */, sal_Int32 nHandle
, const Any
& rValue
)
605 throw (IllegalArgumentException
)
610 case BASERESULTSET_CURSOR_NAME
:
613 bRet
= ( rValue
>>= val
);
614 m_props
[nHandle
] = makeAny( val
);
617 case BASERESULTSET_ESCAPE_PROCESSING
:
618 case BASERESULTSET_IS_BOOKMARKABLE
:
621 bRet
= ( rValue
>>= val
);
622 m_props
[nHandle
] = makeAny( val
);
625 case BASERESULTSET_FETCH_DIRECTION
:
626 case BASERESULTSET_FETCH_SIZE
:
627 case BASERESULTSET_RESULT_SET_CONCURRENCY
:
628 case BASERESULTSET_RESULT_SET_TYPE
:
631 bRet
= ( rValue
>>= val
);
632 m_props
[nHandle
] = makeAny( val
);
637 OUStringBuffer
buf(128);
638 buf
.appendAscii( "pq_resultset: Invalid property handle (" );
639 buf
.append( nHandle
);
640 buf
.appendAscii( ")" );
641 throw IllegalArgumentException( buf
.makeStringAndClear(), *this, 2 );
648 void BaseResultSet::setFastPropertyValue_NoBroadcast(
649 sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
, std::exception
)
651 m_props
[nHandle
] = rValue
;
654 void BaseResultSet::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
656 rValue
= m_props
[nHandle
];
659 Reference
< XPropertySetInfo
> BaseResultSet::getPropertySetInfo()
660 throw(RuntimeException
, std::exception
)
662 return OPropertySetHelper::createPropertySetInfo( getResultSetPropertyArrayHelper() );
665 void BaseResultSet::disposing()
670 void BaseResultSet::checkColumnIndex(sal_Int32 index
) throw ( SQLException
, RuntimeException
)
672 if( index
< 1 || index
> m_fieldCount
)
674 OUStringBuffer
buf(128);
675 buf
.appendAscii( "pq_resultset: index out of range (" );
677 buf
.appendAscii( ", allowed range is 1 to " );
678 buf
.append( m_fieldCount
);
679 buf
.appendAscii( ")" );
680 throw SQLException( buf
.makeStringAndClear(), *this, OUString(), 1, Any() );
685 void BaseResultSet::checkRowIndex( sal_Bool mustBeOnValidRow
)
687 OUStringBuffer
buf( 128 );
688 buf
.appendAscii( "pq_baseresultset: row index out of range, allowed is " );
689 if( mustBeOnValidRow
)
691 if( m_row
< 0 || m_row
>= m_rowCount
)
693 buf
.appendAscii( "0 to " );
694 buf
.append( ((sal_Int32
)(m_rowCount
-1)) );
695 buf
.appendAscii( ", got " );
697 throw SQLException( buf
.makeStringAndClear(), *this, OUString(),1, Any() );
702 if( m_row
< -1 || m_row
> m_rowCount
)
704 buf
.appendAscii( "-1 to " );
705 buf
.append( m_rowCount
);
706 buf
.appendAscii( ", got " );
708 throw SQLException( buf
.makeStringAndClear(), *this, OUString(),1, Any() );
715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */