Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / postgresql / pq_baseresultset.cxx
bloba8af6d40eb7465983ccd9f4d8343a95a18e86a4e
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,
18 * MA 02111-1307 USA
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>
54 using osl::Mutex;
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;
95 if( ! pArrayHelper )
97 MutexGuard guard( Mutex::getGlobalMutex() );
98 if( ! pArrayHelper )
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...
105 Property(
106 OUString("CursorName"), 0,
107 ::cppu::UnoType<OUString>::get() , 0 ),
108 Property(
109 OUString("EscapeProcessing"), 1,
110 ::getBooleanCppuType() , 0 ),
111 Property(
112 OUString("FetchDirection"), 2,
113 ::cppu::UnoType<sal_Int32>::get() , 0 ),
114 Property(
115 OUString("FetchSize"), 3,
116 ::cppu::UnoType<sal_Int32>::get() , 0 ),
117 Property(
118 OUString("IsBookmarkable"), 4,
119 ::getBooleanCppuType() , 0 ),
120 Property(
121 OUString("ResultSetConcurrency"), 5,
122 ::cppu::UnoType<sal_Int32>::get() , 0 ),
123 Property(
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,
138 sal_Int32 rowCount,
139 sal_Int32 colCount,
140 const Reference< com::sun::star::script::XTypeConverter > & tc )
141 : OComponentHelper( refMutex->mutex )
142 , OPropertySetHelper( OComponentHelper::rBHelper )
143 , m_owner( owner )
144 , m_tc( tc )
145 , m_refMutex( refMutex )
146 , m_row( -1 )
147 , m_rowCount( rowCount )
148 , m_fieldCount( colCount )
149 , m_wasNull(false)
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)
164 Any ret;
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 ) );
177 return ret;
180 // void BaseResultSet::close( ) throw (SQLException, RuntimeException)
181 // {
182 // Reference< XInterface > owner;
183 // {
184 // ResultSetGuard guard(*this);
185 // if( m_result )
186 // {
187 // PQclear(m_result );
188 // m_result = 0;
189 // m_row = -1;
190 // }
191 // owner = m_owner;
192 // m_owner.clear();
193 // }
194 // }
196 Sequence<Type > BaseResultSet::getTypes() throw( RuntimeException, std::exception )
198 static cppu::OTypeCollection *pCollection;
199 if( ! pCollection )
201 MutexGuard guard( osl::Mutex::getGlobalMutex() );
202 if( !pCollection )
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)
226 // {
227 // ResultSetGuard guard(*this);
228 // checkClosed();
229 // return new ResultSetMetaData( m_refMutex, this, &m_result );
230 // }
232 sal_Bool BaseResultSet::next( ) throw (SQLException, RuntimeException, std::exception)
234 MutexGuard guard( m_refMutex->mutex );
235 checkClosed();
236 m_row ++;
237 return m_row < m_rowCount;
240 sal_Bool BaseResultSet::isBeforeFirst( ) throw (SQLException, RuntimeException, std::exception)
242 MutexGuard guard( m_refMutex->mutex );
243 checkClosed();
244 return m_row == -1;
247 sal_Bool BaseResultSet::isAfterLast( ) throw (SQLException, RuntimeException, std::exception)
249 MutexGuard guard( m_refMutex->mutex );
250 checkClosed();
251 return m_row >= m_rowCount;
254 sal_Bool BaseResultSet::isFirst( ) throw (SQLException, RuntimeException, std::exception)
256 MutexGuard guard( m_refMutex->mutex );
257 checkClosed();
258 return m_row == 0 && m_rowCount;
261 sal_Bool BaseResultSet::isLast( ) throw (SQLException, RuntimeException, std::exception)
263 MutexGuard guard( m_refMutex->mutex );
264 checkClosed();
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 );
271 checkClosed();
272 m_row = -1;
275 void BaseResultSet::afterLast( ) throw (SQLException, RuntimeException, std::exception)
277 MutexGuard guard( m_refMutex->mutex );
278 checkClosed();
279 m_row = m_rowCount;
282 sal_Bool BaseResultSet::first( ) throw (SQLException, RuntimeException, std::exception)
284 MutexGuard guard( m_refMutex->mutex );
285 checkClosed();
286 bool bRet = ( m_rowCount > 0 );
287 if( bRet )
288 m_row = 0;
289 return bRet;
292 sal_Bool BaseResultSet::last( ) throw (SQLException, RuntimeException, std::exception)
294 MutexGuard guard( m_refMutex->mutex );
295 checkClosed();
296 bool bRet = ( m_rowCount > 0 );
297 if( bRet )
298 m_row = m_rowCount -1;
299 return bRet;
302 sal_Int32 BaseResultSet::getRow( ) throw (SQLException, RuntimeException, std::exception)
304 MutexGuard guard( m_refMutex->mutex );
305 checkClosed();
306 return m_row +1;
309 sal_Bool BaseResultSet::absolute( sal_Int32 row ) throw (SQLException, RuntimeException, std::exception)
311 MutexGuard guard( m_refMutex->mutex );
312 checkClosed();
313 if( row > 0 )
315 m_row = row -1;
316 if( m_row > m_rowCount )
317 m_row = m_rowCount;
319 else
321 m_row = m_rowCount + row;
322 if( m_row < -1 )
323 m_row = -1;
325 return sal_True;
328 sal_Bool BaseResultSet::relative( sal_Int32 rows ) throw (SQLException, RuntimeException, std::exception)
330 MutexGuard guard( m_refMutex->mutex );
331 checkClosed();
332 m_row += rows;
334 if( m_row > m_rowCount )
335 m_row = m_rowCount;
336 else if ( m_row < -1 )
337 m_row = -1;
338 return sal_True;
341 sal_Bool BaseResultSet::previous( ) throw (SQLException, RuntimeException, std::exception)
343 MutexGuard guard( m_refMutex->mutex );
344 checkClosed();
345 bool bRet = ( m_row != -1 );
346 if( bRet )
347 m_row --;
348 return bRet;
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)
358 return sal_False;
361 sal_Bool BaseResultSet::rowInserted( ) throw (SQLException, RuntimeException, std::exception)
363 return sal_False;
366 sal_Bool BaseResultSet::rowDeleted( ) throw (SQLException, RuntimeException, std::exception)
368 return sal_False;
371 Reference< XInterface > BaseResultSet::getStatement() throw (SQLException, RuntimeException, std::exception)
373 MutexGuard guard( m_refMutex->mutex );
374 checkClosed();
375 return m_owner;
379 //----------------- XRow interface ----------------------------------------------------
381 sal_Bool BaseResultSet::wasNull( ) throw (SQLException, RuntimeException, std::exception)
383 return m_wasNull;
386 Any BaseResultSet::convertTo( const Any & val , const Type & type )
388 Any aRet;
391 aRet = m_tc->convertTo( val , type );
393 catch( com::sun::star::lang::IllegalArgumentException & )
395 catch( com::sun::star::script::CannotConvertException & )
397 return aRet;
400 sal_Bool BaseResultSet::getBoolean( sal_Int32 columnIndex ) throw (SQLException, RuntimeException, std::exception)
402 MutexGuard guard( m_refMutex->mutex );
403 checkClosed();
404 checkColumnIndex( columnIndex );
405 checkRowIndex( sal_True /* must be on row */ );
407 OUString str = getString( columnIndex );
409 if( str.getLength() > 0 )
411 switch(str[0])
413 case '1':
414 case 't':
415 case 'T':
416 case 'y':
417 case 'Y':
419 return sal_True;
422 return sal_False;
425 sal_Int8 BaseResultSet::getByte( sal_Int32 columnIndex )
426 throw (SQLException, RuntimeException, std::exception)
428 MutexGuard guard( m_refMutex->mutex );
429 checkClosed();
430 checkColumnIndex( columnIndex );
431 checkRowIndex( sal_True /* must be on row */ );
432 sal_Int8 b = 0;
433 convertTo( getValue( columnIndex ), getCppuType( &b )) >>= b;
434 return b;
437 sal_Int16 BaseResultSet::getShort( sal_Int32 columnIndex )
438 throw (SQLException, RuntimeException, std::exception)
440 MutexGuard guard( m_refMutex->mutex );
441 checkClosed();
442 checkColumnIndex( columnIndex );
443 checkRowIndex( sal_True /* must be on row */ );
444 sal_Int16 i = 0;
445 convertTo( getValue( columnIndex ), getCppuType( &i )) >>= i;
446 return i;
449 OUString BaseResultSet::getString( sal_Int32 columnIndex ) throw (SQLException, RuntimeException, std::exception)
451 MutexGuard guard(m_refMutex->mutex);
452 checkClosed();
453 checkColumnIndex( columnIndex );
454 checkRowIndex( sal_True /* must be on row */ );
455 OUString ret;
456 convertTo( getValue( columnIndex ), getCppuType( &ret ) ) >>= ret;
457 // printf( "BaseResultSet::getString() %s\n" , OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ).getStr() );
458 return ret;
461 sal_Int32 BaseResultSet::getInt( sal_Int32 columnIndex )
462 throw (SQLException, RuntimeException, std::exception)
464 MutexGuard guard( m_refMutex->mutex );
465 checkClosed();
466 checkColumnIndex( columnIndex );
467 checkRowIndex( sal_True /* must be on row */ );
468 sal_Int32 i = 0;
469 convertTo( getValue( columnIndex ), getCppuType( &i )) >>= i;
470 return i;
473 sal_Int64 BaseResultSet::getLong( sal_Int32 columnIndex )
474 throw (SQLException, RuntimeException, std::exception)
476 MutexGuard guard( m_refMutex->mutex );
477 checkClosed();
478 checkColumnIndex( columnIndex );
479 checkRowIndex( sal_True /* must be on row */ );
480 sal_Int64 i = 0;
481 convertTo( getValue( columnIndex ), getCppuType( &i )) >>= i;
482 return i;
485 float BaseResultSet::getFloat( sal_Int32 columnIndex )
486 throw (SQLException, RuntimeException, std::exception)
488 MutexGuard guard( m_refMutex->mutex );
489 checkClosed();
490 checkColumnIndex( columnIndex );
491 checkRowIndex( sal_True /* must be on row */ );
492 float f = 0.;
493 convertTo( getValue( columnIndex ), getCppuType( &f )) >>= f;
494 return f;
497 double BaseResultSet::getDouble( sal_Int32 columnIndex )
498 throw (SQLException, RuntimeException, std::exception)
500 MutexGuard guard( m_refMutex->mutex );
501 checkClosed();
502 checkColumnIndex( columnIndex );
503 double d = 0.;
504 convertTo( getValue( columnIndex ), getCppuType( &d )) >>= d;
505 return d;
508 Sequence< sal_Int8 > BaseResultSet::getBytes( sal_Int32 columnIndex )
509 throw (SQLException, RuntimeException, std::exception)
511 MutexGuard guard( m_refMutex->mutex );
512 checkClosed();
513 checkColumnIndex( columnIndex );
514 checkRowIndex( sal_True /* must be on row */ );
516 Sequence< sal_Int8 > ret;
517 OUString ustr;
518 if( ! (getValue( columnIndex ) >>= ustr) )
519 m_wasNull = true;
520 else
522 // if this is a binary, it must contain escaped data !
523 OString val = OUStringToOString( ustr, RTL_TEXTENCODING_ASCII_US );
525 size_t length;
526 char * res = (char*) PQunescapeBytea( (unsigned char *)val.getStr() , &length);
527 ret = Sequence< sal_Int8 > ( (sal_Int8*)res, length );
528 if( res )
529 free( res );
531 return ret;
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)
557 return 0;
560 Reference< ::com::sun::star::io::XInputStream > BaseResultSet::getCharacterStream( sal_Int32 /* columnIndex */ )
561 throw (SQLException, RuntimeException, std::exception)
563 return 0;
566 Any BaseResultSet::getObject(
567 sal_Int32 /* columnIndex */,
568 const Reference< ::com::sun::star::container::XNameAccess >& /* typeMap */ )
569 throw (SQLException, RuntimeException, std::exception)
571 return Any();
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)
607 bool bRet;
608 switch( nHandle )
610 case BASERESULTSET_CURSOR_NAME:
612 OUString val;
613 bRet = ( rValue >>= val );
614 m_props[nHandle] = makeAny( val );
615 break;
617 case BASERESULTSET_ESCAPE_PROCESSING:
618 case BASERESULTSET_IS_BOOKMARKABLE:
620 bool val(false);
621 bRet = ( rValue >>= val );
622 m_props[nHandle] = makeAny( val );
623 break;
625 case BASERESULTSET_FETCH_DIRECTION:
626 case BASERESULTSET_FETCH_SIZE:
627 case BASERESULTSET_RESULT_SET_CONCURRENCY:
628 case BASERESULTSET_RESULT_SET_TYPE:
630 sal_Int32 val;
631 bRet = ( rValue >>= val );
632 m_props[nHandle] = makeAny( val );
633 break;
635 default:
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 );
644 return bRet;
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()
667 close();
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 (" );
676 buf.append( index );
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 " );
696 buf.append( m_row );
697 throw SQLException( buf.makeStringAndClear(), *this, OUString(),1, Any() );
700 else
702 if( m_row < -1 || m_row > m_rowCount )
704 buf.appendAscii( "-1 to " );
705 buf.append( m_rowCount );
706 buf.appendAscii( ", got " );
707 buf.append( m_row );
708 throw SQLException( buf.makeStringAndClear(), *this, OUString(),1, Any() );
715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */