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 * Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
33 * The contents of this file are subject to the Mozilla Public License Version
34 * 1.1 (the "License"); you may not use this file except in compliance with
35 * the License or as specified alternatively below. You may obtain a copy of
36 * the License at http://www.mozilla.org/MPL/
38 * Software distributed under the License is distributed on an "AS IS" basis,
39 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40 * for the specific language governing rights and limitations under the
43 * Major Contributor(s):
44 * [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
46 * All Rights Reserved.
48 * For minor contributions see the git repository.
50 * Alternatively, the contents of this file may be used under the terms of
51 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
52 * the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
53 * in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
54 * instead of those above.
56 ************************************************************************/
58 #include <osl/thread.h>
60 #include <rtl/ustrbuf.hxx>
62 #include <cppuhelper/typeprovider.hxx>
63 #include <cppuhelper/queryinterface.hxx>
65 #include "pq_tools.hxx"
66 #include "pq_array.hxx"
67 #include "pq_statement.hxx"
68 #include "pq_baseresultset.hxx"
69 #include "pq_resultsetmetadata.hxx"
71 #include <com/sun/star/lang/DisposedException.hpp>
74 using osl::MutexGuard
;
77 using rtl::OUStringToOString
;
78 using rtl::OUStringBuffer
;
81 using com::sun::star::beans::XPropertySetInfo
;
82 using com::sun::star::beans::XPropertySet
;
83 using com::sun::star::beans::XMultiPropertySet
;
84 using com::sun::star::beans::XFastPropertySet
;
86 using com::sun::star::uno::Any
;
87 using com::sun::star::uno::makeAny
;
88 using com::sun::star::uno::Type
;
89 using com::sun::star::uno::RuntimeException
;
90 using com::sun::star::uno::Exception
;
91 using com::sun::star::uno::Sequence
;
92 using com::sun::star::uno::Reference
;
93 using com::sun::star::uno::XInterface
;
95 using com::sun::star::lang::IllegalArgumentException
;
97 using com::sun::star::sdbc::XWarningsSupplier
;
98 using com::sun::star::sdbc::XCloseable
;
99 using com::sun::star::sdbc::XStatement
;
100 using com::sun::star::sdbc::XResultSet
;
101 using com::sun::star::sdbc::XConnection
;
102 using com::sun::star::sdbc::SQLException
;
103 using com::sun::star::sdbc::XRow
;
104 using com::sun::star::sdbc::XColumnLocate
;
105 using com::sun::star::sdbc::XResultSetMetaData
;
106 using com::sun::star::sdbc::XResultSetMetaDataSupplier
;
109 using com::sun::star::beans::Property
;
111 namespace pq_sdbc_driver
113 static ::cppu::IPropertyArrayHelper
& getResultSetPropertyArrayHelper()
115 static ::cppu::IPropertyArrayHelper
*pArrayHelper
;
118 MutexGuard
guard( Mutex::getGlobalMutex() );
121 static Property aTable
[] =
123 // LEM TODO: this needs to be kept in sync with other, e.g. pq_statics.css:508
124 // Should really share!
125 // At least use for the handles the #define'd values in .hxx file...
127 OUString( RTL_CONSTASCII_USTRINGPARAM("CursorName") ), 0,
128 ::getCppuType( (OUString
*)0) , 0 ),
130 OUString( RTL_CONSTASCII_USTRINGPARAM("EscapeProcessing") ), 1,
131 ::getBooleanCppuType() , 0 ),
133 OUString( RTL_CONSTASCII_USTRINGPARAM("FetchDirection") ), 2,
134 ::getCppuType( (sal_Int32
*)0) , 0 ),
136 OUString( RTL_CONSTASCII_USTRINGPARAM("FetchSize") ), 3,
137 ::getCppuType( (sal_Int32
*)0) , 0 ),
139 OUString( RTL_CONSTASCII_USTRINGPARAM("IsBookmarkable") ), 4,
140 ::getBooleanCppuType() , 0 ),
142 OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetConcurrency") ), 5,
143 ::getCppuType( (sal_Int32
*)0) , 0 ),
145 OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetType") ), 6,
146 ::getCppuType( (sal_Int32
*)0) , 0 )
148 OSL_ASSERT( sizeof(aTable
) / sizeof(Property
) == BASERESULTSET_SIZE
);
149 static ::cppu::OPropertyArrayHelper
arrayHelper( aTable
, BASERESULTSET_SIZE
, sal_True
);
150 pArrayHelper
= &arrayHelper
;
153 return *pArrayHelper
;
156 BaseResultSet::BaseResultSet(
157 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
158 const Reference
< XInterface
> & owner
,
161 const Reference
< com::sun::star::script::XTypeConverter
> & tc
)
162 : OComponentHelper( refMutex
->mutex
),
163 OPropertySetHelper( OComponentHelper::rBHelper
),
166 m_refMutex( refMutex
),
168 m_rowCount( rowCount
),
169 m_fieldCount( colCount
)
171 POSTGRE_TRACE( "ctor BaseResultSet" );
174 // LEM TODO: refMutex->mutex should live longer than OComponentHelper,
175 // but calling OComponentHelper::dispose explicitly here calls
176 // BaseResultSet::~BaseResultSet in an infinite loop :(
177 BaseResultSet::~BaseResultSet()
179 POSTGRE_TRACE( "dtor BaseResultSet" );
182 Any
BaseResultSet::queryInterface( const Type
& reqType
) throw (RuntimeException
)
186 ret
= OComponentHelper::queryInterface( reqType
);
187 if( ! ret
.hasValue() )
188 ret
= ::cppu::queryInterface( reqType
,
189 static_cast< XResultSet
* > ( this ),
190 static_cast< XResultSetMetaDataSupplier
* > ( this ),
191 static_cast< XRow
* > ( this ),
192 static_cast< XColumnLocate
* > ( this ),
193 static_cast< XCloseable
* > ( this ),
194 static_cast< XPropertySet
* > ( this ),
195 static_cast< XMultiPropertySet
* > ( this ),
196 static_cast< XFastPropertySet
* > ( this ) );
200 // void BaseResultSet::close( ) throw (SQLException, RuntimeException)
202 // Reference< XInterface > owner;
204 // ResultSetGuard guard(*this);
207 // PQclear(m_result );
216 Sequence
<Type
> BaseResultSet::getTypes() throw( RuntimeException
)
218 static cppu::OTypeCollection
*pCollection
;
221 MutexGuard
guard( osl::Mutex::getGlobalMutex() );
224 static cppu::OTypeCollection
collection(
225 getCppuType( (Reference
< XResultSet
> *) 0 ),
226 getCppuType( (Reference
< XResultSetMetaDataSupplier
> *) 0 ),
227 getCppuType( (Reference
< XRow
> *) 0 ),
228 getCppuType( (Reference
< XColumnLocate
> *) 0 ),
229 getCppuType( (Reference
< XCloseable
> *) 0 ),
230 getCppuType( (Reference
< XPropertySet
>*) 0 ),
231 getCppuType( (Reference
< XFastPropertySet
> *) 0 ),
232 getCppuType( (Reference
< XMultiPropertySet
> *) 0 ),
233 OComponentHelper::getTypes());
234 pCollection
= &collection
;
237 return pCollection
->getTypes();
240 Sequence
< sal_Int8
> BaseResultSet::getImplementationId() throw( RuntimeException
)
242 static cppu::OImplementationId
*pId
;
245 MutexGuard
guard( osl::Mutex::getGlobalMutex() );
248 static cppu::OImplementationId
id(sal_False
);
252 return pId
->getImplementationId();
255 // Reference< XResultSetMetaData > BaseResultSet::getMetaData( ) throw (SQLException, RuntimeException)
257 // ResultSetGuard guard(*this);
259 // return new ResultSetMetaData( m_refMutex, this, &m_result );
262 sal_Bool
BaseResultSet::next( ) throw (SQLException
, RuntimeException
)
264 MutexGuard
guard( m_refMutex
->mutex
);
267 return m_row
< m_rowCount
;
270 sal_Bool
BaseResultSet::isBeforeFirst( ) throw (SQLException
, RuntimeException
)
272 MutexGuard
guard( m_refMutex
->mutex
);
277 sal_Bool
BaseResultSet::isAfterLast( ) throw (SQLException
, RuntimeException
)
279 MutexGuard
guard( m_refMutex
->mutex
);
281 return m_row
>= m_rowCount
;
284 sal_Bool
BaseResultSet::isFirst( ) throw (SQLException
, RuntimeException
)
286 MutexGuard
guard( m_refMutex
->mutex
);
288 return m_row
== 0 && m_rowCount
;
291 sal_Bool
BaseResultSet::isLast( ) throw (SQLException
, RuntimeException
)
293 MutexGuard
guard( m_refMutex
->mutex
);
295 return m_row
>= 0 && m_row
+ 1 == m_rowCount
;
298 void BaseResultSet::beforeFirst( ) throw (SQLException
, RuntimeException
)
300 MutexGuard
guard( m_refMutex
->mutex
);
305 void BaseResultSet::afterLast( ) throw (SQLException
, RuntimeException
)
307 MutexGuard
guard( m_refMutex
->mutex
);
312 sal_Bool
BaseResultSet::first( ) throw (SQLException
, RuntimeException
)
314 MutexGuard
guard( m_refMutex
->mutex
);
316 sal_Bool bRet
= ( m_rowCount
> 0 );
322 sal_Bool
BaseResultSet::last( ) throw (SQLException
, RuntimeException
)
324 MutexGuard
guard( m_refMutex
->mutex
);
326 sal_Bool bRet
= ( m_rowCount
> 0 );
328 m_row
= m_rowCount
-1;
332 sal_Int32
BaseResultSet::getRow( ) throw (SQLException
, RuntimeException
)
334 MutexGuard
guard( m_refMutex
->mutex
);
339 sal_Bool
BaseResultSet::absolute( sal_Int32 row
) throw (SQLException
, RuntimeException
)
341 MutexGuard
guard( m_refMutex
->mutex
);
346 if( m_row
> m_rowCount
)
351 m_row
= m_rowCount
+ row
;
358 sal_Bool
BaseResultSet::relative( sal_Int32 rows
) throw (SQLException
, RuntimeException
)
360 MutexGuard
guard( m_refMutex
->mutex
);
364 if( m_row
> m_rowCount
)
366 else if ( m_row
< -1 )
371 sal_Bool
BaseResultSet::previous( ) throw (SQLException
, RuntimeException
)
373 MutexGuard
guard( m_refMutex
->mutex
);
375 sal_Bool bRet
= ( m_row
!= -1 );
381 void BaseResultSet::refreshRow( ) throw (SQLException
, RuntimeException
)
383 // TODO: not supported for now
386 sal_Bool
BaseResultSet::rowUpdated( ) throw (SQLException
, RuntimeException
)
391 sal_Bool
BaseResultSet::rowInserted( ) throw (SQLException
, RuntimeException
)
396 sal_Bool
BaseResultSet::rowDeleted( ) throw (SQLException
, RuntimeException
)
401 Reference
< XInterface
> BaseResultSet::getStatement() throw (SQLException
, RuntimeException
)
403 MutexGuard
guard( m_refMutex
->mutex
);
409 //----------------- XRow interface ----------------------------------------------------
411 sal_Bool
BaseResultSet::wasNull( ) throw (SQLException
, RuntimeException
)
416 Any
BaseResultSet::convertTo( const Any
& val
, const Type
& type
)
421 aRet
= m_tc
->convertTo( val
, type
);
423 catch( com::sun::star::lang::IllegalArgumentException
& )
425 catch( com::sun::star::script::CannotConvertException
& )
430 sal_Bool
BaseResultSet::getBoolean( sal_Int32 columnIndex
) throw (SQLException
, RuntimeException
)
432 MutexGuard
guard( m_refMutex
->mutex
);
434 checkColumnIndex( columnIndex
);
435 checkRowIndex( sal_True
/* must be on row */ );
437 OUString str
= getString( columnIndex
);
439 if( str
.getLength() > 0 )
455 sal_Int8
BaseResultSet::getByte( sal_Int32 columnIndex
)
456 throw (SQLException
, RuntimeException
)
458 MutexGuard
guard( m_refMutex
->mutex
);
460 checkColumnIndex( columnIndex
);
461 checkRowIndex( sal_True
/* must be on row */ );
463 convertTo( getValue( columnIndex
), getCppuType( &b
)) >>= b
;
467 sal_Int16
BaseResultSet::getShort( sal_Int32 columnIndex
)
468 throw (SQLException
, RuntimeException
)
470 MutexGuard
guard( m_refMutex
->mutex
);
472 checkColumnIndex( columnIndex
);
473 checkRowIndex( sal_True
/* must be on row */ );
475 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
479 OUString
BaseResultSet::getString( sal_Int32 columnIndex
) throw (SQLException
, RuntimeException
)
481 MutexGuard
guard(m_refMutex
->mutex
);
483 checkColumnIndex( columnIndex
);
484 checkRowIndex( sal_True
/* must be on row */ );
486 convertTo( getValue( columnIndex
), getCppuType( &ret
) ) >>= ret
;
487 // printf( "BaseResultSet::getString() %s\n" , OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ).getStr() );
491 sal_Int32
BaseResultSet::getInt( sal_Int32 columnIndex
)
492 throw (SQLException
, RuntimeException
)
494 MutexGuard
guard( m_refMutex
->mutex
);
496 checkColumnIndex( columnIndex
);
497 checkRowIndex( sal_True
/* must be on row */ );
499 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
503 sal_Int64
BaseResultSet::getLong( sal_Int32 columnIndex
)
504 throw (SQLException
, RuntimeException
)
506 MutexGuard
guard( m_refMutex
->mutex
);
508 checkColumnIndex( columnIndex
);
509 checkRowIndex( sal_True
/* must be on row */ );
511 convertTo( getValue( columnIndex
), getCppuType( &i
)) >>= i
;
515 float BaseResultSet::getFloat( sal_Int32 columnIndex
)
516 throw (SQLException
, RuntimeException
)
518 MutexGuard
guard( m_refMutex
->mutex
);
520 checkColumnIndex( columnIndex
);
521 checkRowIndex( sal_True
/* must be on row */ );
523 convertTo( getValue( columnIndex
), getCppuType( &f
)) >>= f
;
527 double BaseResultSet::getDouble( sal_Int32 columnIndex
)
528 throw (SQLException
, RuntimeException
)
530 MutexGuard
guard( m_refMutex
->mutex
);
532 checkColumnIndex( columnIndex
);
534 convertTo( getValue( columnIndex
), getCppuType( &d
)) >>= d
;
538 Sequence
< sal_Int8
> BaseResultSet::getBytes( sal_Int32 columnIndex
)
539 throw (SQLException
, RuntimeException
)
541 MutexGuard
guard( m_refMutex
->mutex
);
543 checkColumnIndex( columnIndex
);
544 checkRowIndex( sal_True
/* must be on row */ );
546 Sequence
< sal_Int8
> ret
;
548 if( ! (getValue( columnIndex
) >>= ustr
) )
552 // if this is a binary, it must contain escaped data !
553 OString val
= rtl::OUStringToOString( ustr
, RTL_TEXTENCODING_ASCII_US
);
556 char * res
= (char*) PQunescapeBytea( (unsigned char *)val
.getStr() , &length
);
557 ret
= Sequence
< sal_Int8
> ( (sal_Int8
*)res
, length
);
565 ::com::sun::star::util::Date
BaseResultSet::getDate( sal_Int32 columnIndex
)
566 throw (SQLException
, RuntimeException
)
568 return string2Date( getString( columnIndex
) );
571 ::com::sun::star::util::Time
BaseResultSet::getTime( sal_Int32 columnIndex
)
572 throw (SQLException
, RuntimeException
)
574 return string2Time( getString( columnIndex
) );
577 ::com::sun::star::util::DateTime
BaseResultSet::getTimestamp( sal_Int32 columnIndex
)
578 throw (SQLException
, RuntimeException
)
580 return string2DateTime( getString( columnIndex
) );
583 // LEM TODO: these look like they are missing an actual implementation
584 Reference
< ::com::sun::star::io::XInputStream
> BaseResultSet::getBinaryStream( sal_Int32
/* columnIndex */ )
585 throw (SQLException
, RuntimeException
)
590 Reference
< ::com::sun::star::io::XInputStream
> BaseResultSet::getCharacterStream( sal_Int32
/* columnIndex */ )
591 throw (SQLException
, RuntimeException
)
596 Any
BaseResultSet::getObject(
597 sal_Int32
/* columnIndex */,
598 const Reference
< ::com::sun::star::container::XNameAccess
>& /* typeMap */ )
599 throw (SQLException
, RuntimeException
)
604 Reference
< ::com::sun::star::sdbc::XRef
> BaseResultSet::getRef( sal_Int32
/* columnIndex */ )
605 throw (SQLException
, RuntimeException
)
607 return Reference
< com::sun::star::sdbc::XRef
> ();
610 Reference
< ::com::sun::star::sdbc::XBlob
> BaseResultSet::getBlob( sal_Int32
/* columnIndex */ )
611 throw (SQLException
, RuntimeException
)
613 return Reference
< com::sun::star::sdbc::XBlob
> ();
616 Reference
< ::com::sun::star::sdbc::XClob
> BaseResultSet::getClob( sal_Int32
/* columnIndex */ )
617 throw (SQLException
, RuntimeException
)
619 return Reference
< com::sun::star::sdbc::XClob
> ();
622 Reference
< ::com::sun::star::sdbc::XArray
> BaseResultSet::getArray( sal_Int32 columnIndex
)
623 throw (SQLException
, RuntimeException
)
625 return new Array( m_refMutex
, parseArray( getString( columnIndex
) ), *this, m_tc
);
628 ::cppu::IPropertyArrayHelper
& BaseResultSet::getInfoHelper()
630 return getResultSetPropertyArrayHelper();
633 sal_Bool
BaseResultSet::convertFastPropertyValue(
634 Any
& /* rConvertedValue */, Any
& /* rOldValue */, sal_Int32 nHandle
, const Any
& rValue
)
635 throw (IllegalArgumentException
)
640 case BASERESULTSET_CURSOR_NAME
:
643 bRet
= ( rValue
>>= val
);
644 m_props
[nHandle
] = makeAny( val
);
647 case BASERESULTSET_ESCAPE_PROCESSING
:
648 case BASERESULTSET_IS_BOOKMARKABLE
:
651 bRet
= ( rValue
>>= val
);
652 m_props
[nHandle
] = makeAny( val
);
655 case BASERESULTSET_FETCH_DIRECTION
:
656 case BASERESULTSET_FETCH_SIZE
:
657 case BASERESULTSET_RESULT_SET_CONCURRENCY
:
658 case BASERESULTSET_RESULT_SET_TYPE
:
661 bRet
= ( rValue
>>= val
);
662 m_props
[nHandle
] = makeAny( val
);
667 OUStringBuffer
buf(128);
668 buf
.appendAscii( "pq_resultset: Invalid property handle (" );
669 buf
.append( nHandle
);
670 buf
.appendAscii( ")" );
671 throw IllegalArgumentException( buf
.makeStringAndClear(), *this, 2 );
678 void BaseResultSet::setFastPropertyValue_NoBroadcast(
679 sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
681 m_props
[nHandle
] = rValue
;
684 void BaseResultSet::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
686 rValue
= m_props
[nHandle
];
689 Reference
< XPropertySetInfo
> BaseResultSet::getPropertySetInfo()
690 throw(RuntimeException
)
692 return OPropertySetHelper::createPropertySetInfo( getResultSetPropertyArrayHelper() );
695 void BaseResultSet::disposing()
700 void BaseResultSet::checkColumnIndex(sal_Int32 index
) throw ( SQLException
, RuntimeException
)
702 if( index
< 1 || index
> m_fieldCount
)
704 OUStringBuffer
buf(128);
705 buf
.appendAscii( "pq_resultset: index out of range (" );
707 buf
.appendAscii( ", allowed range is 1 to " );
708 buf
.append( m_fieldCount
);
709 buf
.appendAscii( ")" );
710 throw SQLException( buf
.makeStringAndClear(), *this, OUString(), 1, Any() );
715 void BaseResultSet::checkRowIndex( sal_Bool mustBeOnValidRow
)
717 OUStringBuffer
buf( 128 );
718 buf
.appendAscii( "pq_baseresultset: row index out of range, allowed is " );
719 if( mustBeOnValidRow
)
721 if( m_row
< 0 || m_row
>= m_rowCount
)
723 buf
.appendAscii( "0 to " );
724 buf
.append( ((sal_Int32
)(m_rowCount
-1)) );
725 buf
.appendAscii( ", got " );
727 throw SQLException( buf
.makeStringAndClear(), *this, OUString(),1, Any() );
732 if( m_row
< -1 || m_row
> m_rowCount
)
734 buf
.appendAscii( "-1 to " );
735 buf
.append( m_rowCount
);
736 buf
.appendAscii( ", got " );
738 throw SQLException( buf
.makeStringAndClear(), *this, OUString(),1, Any() );