tdf#144694 In direct SQL dialog, activate options 'Run SQL command
[LibreOffice.git] / connectivity / source / drivers / postgresql / pq_baseresultset.cxx
blob274a0a209a173fcd5cb961fa54ccb57ca5000de2
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 <comphelper/sequence.hxx>
39 #include "pq_tools.hxx"
40 #include "pq_array.hxx"
41 #include "pq_baseresultset.hxx"
43 #include <com/sun/star/script/CannotConvertException.hpp>
44 #include <com/sun/star/sdbc/SQLException.hpp>
45 #include <connectivity/dbconversion.hxx>
47 using osl::MutexGuard;
50 using com::sun::star::beans::XPropertySetInfo;
52 using com::sun::star::uno::Any;
53 using com::sun::star::uno::Type;
54 using com::sun::star::uno::Sequence;
55 using com::sun::star::uno::Reference;
56 using com::sun::star::uno::XInterface;
58 using com::sun::star::lang::IllegalArgumentException;
60 using com::sun::star::sdbc::SQLException;
63 using com::sun::star::beans::Property;
65 using namespace dbtools;
67 namespace pq_sdbc_driver
69 static ::cppu::IPropertyArrayHelper & getResultSetPropertyArrayHelper()
71 // LEM TODO: this needs to be kept in sync with other, e.g. pq_statics.css:508
72 // Should really share!
73 // At least use for the handles the #define'd values in .hxx file...
74 static ::cppu::OPropertyArrayHelper arrayHelper(
75 Sequence<Property>{
76 Property(
77 u"CursorName"_ustr, 0,
78 ::cppu::UnoType<OUString>::get() , 0 ),
79 Property(
80 u"EscapeProcessing"_ustr, 1,
81 cppu::UnoType<bool>::get() , 0 ),
82 Property(
83 u"FetchDirection"_ustr, 2,
84 ::cppu::UnoType<sal_Int32>::get() , 0 ),
85 Property(
86 u"FetchSize"_ustr, 3,
87 ::cppu::UnoType<sal_Int32>::get() , 0 ),
88 Property(
89 u"IsBookmarkable"_ustr, 4,
90 cppu::UnoType<bool>::get() , 0 ),
91 Property(
92 u"ResultSetConcurrency"_ustr, 5,
93 ::cppu::UnoType<sal_Int32>::get() , 0 ),
94 Property(
95 u"ResultSetType"_ustr, 6,
96 ::cppu::UnoType<sal_Int32>::get() , 0 )},
97 true );
98 return arrayHelper;
101 BaseResultSet::BaseResultSet(
102 const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
103 const Reference< XInterface > & owner,
104 sal_Int32 rowCount,
105 sal_Int32 colCount,
106 const Reference< css::script::XTypeConverter > & tc )
107 : BaseResultSet_BASE( refMutex->GetMutex() )
108 , OPropertySetHelper( BaseResultSet_BASE::rBHelper )
109 , m_owner( owner )
110 , m_tc( tc )
111 , m_xMutex( refMutex )
112 , m_row( -1 )
113 , m_rowCount( rowCount )
114 , m_fieldCount( colCount )
115 , m_wasNull(false)
119 // LEM TODO: refMutex->GetMutex() should live longer than OComponentHelper,
120 // but calling OComponentHelper::dispose explicitly here calls
121 // BaseResultSet::~BaseResultSet in an infinite loop :(
122 BaseResultSet::~BaseResultSet()
126 Any BaseResultSet::queryInterface( const Type & rType )
128 Any aRet = BaseResultSet_BASE::queryInterface(rType);
129 return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
132 // void BaseResultSet::close( ) throw (SQLException, RuntimeException)
133 // {
134 // Reference< XInterface > owner;
135 // {
136 // ResultSetGuard guard(*this);
137 // if( m_result )
138 // {
139 // PQclear(m_result );
140 // m_result = 0;
141 // m_row = -1;
142 // }
143 // owner = m_owner;
144 // m_owner.clear();
145 // }
146 // }
148 Sequence<Type > BaseResultSet::getTypes()
150 static Sequence< Type > collection(
151 ::comphelper::concatSequences(
152 OPropertySetHelper::getTypes(),
153 BaseResultSet_BASE::getTypes()));
154 return collection;
157 Sequence< sal_Int8> BaseResultSet::getImplementationId()
159 return css::uno::Sequence<sal_Int8>();
162 // Reference< XResultSetMetaData > BaseResultSet::getMetaData( ) throw (SQLException, RuntimeException)
163 // {
164 // ResultSetGuard guard(*this);
165 // checkClosed();
166 // return new ResultSetMetaData( m_xMutex, this, &m_result );
167 // }
169 sal_Bool BaseResultSet::next( )
171 MutexGuard guard( m_xMutex->GetMutex() );
172 checkClosed();
173 m_row ++;
174 return m_row < m_rowCount;
177 sal_Bool BaseResultSet::isBeforeFirst( )
179 MutexGuard guard( m_xMutex->GetMutex() );
180 checkClosed();
181 return m_row == -1;
184 sal_Bool BaseResultSet::isAfterLast( )
186 MutexGuard guard( m_xMutex->GetMutex() );
187 checkClosed();
188 return m_row >= m_rowCount;
191 sal_Bool BaseResultSet::isFirst( )
193 MutexGuard guard( m_xMutex->GetMutex() );
194 checkClosed();
195 return m_row == 0 && m_rowCount;
198 sal_Bool BaseResultSet::isLast( )
200 MutexGuard guard( m_xMutex->GetMutex() );
201 checkClosed();
202 return m_row >= 0 && m_row + 1 == m_rowCount;
205 void BaseResultSet::beforeFirst( )
207 MutexGuard guard( m_xMutex->GetMutex() );
208 checkClosed();
209 m_row = -1;
212 void BaseResultSet::afterLast( )
214 MutexGuard guard( m_xMutex->GetMutex() );
215 checkClosed();
216 m_row = m_rowCount;
219 sal_Bool BaseResultSet::first( )
221 MutexGuard guard( m_xMutex->GetMutex() );
222 checkClosed();
223 bool bRet = ( m_rowCount > 0 );
224 if( bRet )
225 m_row = 0;
226 return bRet;
229 sal_Bool BaseResultSet::last( )
231 MutexGuard guard( m_xMutex->GetMutex() );
232 checkClosed();
233 bool bRet = ( m_rowCount > 0 );
234 if( bRet )
235 m_row = m_rowCount -1;
236 return bRet;
239 sal_Int32 BaseResultSet::getRow( )
241 MutexGuard guard( m_xMutex->GetMutex() );
242 checkClosed();
243 return m_row +1;
246 sal_Bool BaseResultSet::absolute( sal_Int32 row )
248 MutexGuard guard( m_xMutex->GetMutex() );
249 checkClosed();
250 if( row > 0 )
252 m_row = row -1;
253 if( m_row > m_rowCount )
254 m_row = m_rowCount;
256 else
258 m_row = m_rowCount + row;
259 if( m_row < -1 )
260 m_row = -1;
262 return true;
265 sal_Bool BaseResultSet::relative( sal_Int32 rows )
267 MutexGuard guard( m_xMutex->GetMutex() );
268 checkClosed();
269 m_row += rows;
271 if( m_row > m_rowCount )
272 m_row = m_rowCount;
273 else if ( m_row < -1 )
274 m_row = -1;
275 return true;
278 sal_Bool BaseResultSet::previous( )
280 MutexGuard guard( m_xMutex->GetMutex() );
281 checkClosed();
282 bool bRet = ( m_row != -1 );
283 if( bRet )
284 m_row --;
285 return bRet;
288 void BaseResultSet::refreshRow( )
290 // TODO: not supported for now
293 sal_Bool BaseResultSet::rowUpdated( )
295 return false;
298 sal_Bool BaseResultSet::rowInserted( )
300 return false;
303 sal_Bool BaseResultSet::rowDeleted( )
305 return false;
308 Reference< XInterface > BaseResultSet::getStatement()
310 MutexGuard guard( m_xMutex->GetMutex() );
311 checkClosed();
312 return m_owner;
316 //----------------- XRow interface ----------------------------------------------------
318 sal_Bool BaseResultSet::wasNull( )
320 return m_wasNull;
323 Any BaseResultSet::convertTo( const Any & val , const Type & type )
325 Any aRet;
328 aRet = m_tc->convertTo( val , type );
330 catch( css::lang::IllegalArgumentException & )
332 catch( css::script::CannotConvertException & )
334 return aRet;
337 sal_Bool BaseResultSet::getBoolean( sal_Int32 columnIndex )
339 MutexGuard guard( m_xMutex->GetMutex() );
340 checkClosed();
341 checkColumnIndex( columnIndex );
342 checkRowIndex();
344 OUString str = getString( columnIndex );
346 if( str.getLength() > 0 )
348 switch(str[0])
350 case '1':
351 case 't':
352 case 'T':
353 case 'y':
354 case 'Y':
356 return true;
359 return false;
362 sal_Int8 BaseResultSet::getByte( sal_Int32 columnIndex )
364 MutexGuard guard( m_xMutex->GetMutex() );
365 checkClosed();
366 checkColumnIndex( columnIndex );
367 checkRowIndex();
368 sal_Int8 b = 0;
369 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(b)>::get()) >>= b;
370 return b;
373 sal_Int16 BaseResultSet::getShort( sal_Int32 columnIndex )
375 MutexGuard guard( m_xMutex->GetMutex() );
376 checkClosed();
377 checkColumnIndex( columnIndex );
378 checkRowIndex();
379 sal_Int16 i = 0;
380 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
381 return i;
384 OUString BaseResultSet::getString( sal_Int32 columnIndex )
386 MutexGuard guard(m_xMutex->GetMutex());
387 checkClosed();
388 checkColumnIndex( columnIndex );
389 checkRowIndex();
390 OUString ret;
391 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(ret)>::get() ) >>= ret;
392 // printf( "BaseResultSet::getString() %s\n" , OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ).getStr() );
393 return ret;
396 sal_Int32 BaseResultSet::getInt( sal_Int32 columnIndex )
398 MutexGuard guard( m_xMutex->GetMutex() );
399 checkClosed();
400 checkColumnIndex( columnIndex );
401 checkRowIndex();
402 sal_Int32 i = 0;
403 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
404 return i;
407 sal_Int64 BaseResultSet::getLong( sal_Int32 columnIndex )
409 MutexGuard guard( m_xMutex->GetMutex() );
410 checkClosed();
411 checkColumnIndex( columnIndex );
412 checkRowIndex();
413 sal_Int64 i = 0;
414 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
415 return i;
418 float BaseResultSet::getFloat( sal_Int32 columnIndex )
420 MutexGuard guard( m_xMutex->GetMutex() );
421 checkClosed();
422 checkColumnIndex( columnIndex );
423 checkRowIndex();
424 float f = 0.;
425 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(f)>::get()) >>= f;
426 return f;
429 double BaseResultSet::getDouble( sal_Int32 columnIndex )
431 MutexGuard guard( m_xMutex->GetMutex() );
432 checkClosed();
433 checkColumnIndex( columnIndex );
434 double d = 0.;
435 convertTo( getValue( columnIndex ), cppu::UnoType<decltype(d)>::get()) >>= d;
436 return d;
439 Sequence< sal_Int8 > BaseResultSet::getBytes( sal_Int32 columnIndex )
441 MutexGuard guard( m_xMutex->GetMutex() );
442 checkClosed();
443 checkColumnIndex( columnIndex );
444 checkRowIndex();
446 Sequence< sal_Int8 > ret;
447 OUString ustr;
448 if( ! (getValue( columnIndex ) >>= ustr) )
449 m_wasNull = true;
450 else
452 // if this is a binary, it must contain escaped data !
453 OString val = OUStringToOString( ustr, RTL_TEXTENCODING_ASCII_US );
455 size_t length;
456 char * res = reinterpret_cast<char*>(PQunescapeBytea( reinterpret_cast<unsigned char const *>(val.getStr()), &length));
457 ret = Sequence< sal_Int8 > ( reinterpret_cast<sal_Int8*>(res), length );
458 if( res )
459 PQfreemem( res );
461 return ret;
465 css::util::Date BaseResultSet::getDate( sal_Int32 columnIndex )
467 return DBTypeConversion::toDate( getString( columnIndex ) );
470 css::util::Time BaseResultSet::getTime( sal_Int32 columnIndex )
472 return DBTypeConversion::toTime( getString( columnIndex ) );
475 css::util::DateTime BaseResultSet::getTimestamp( sal_Int32 columnIndex )
477 return DBTypeConversion::toDateTime( getString( columnIndex ) );
480 // LEM TODO: these look like they are missing an actual implementation
481 Reference< css::io::XInputStream > BaseResultSet::getBinaryStream( sal_Int32 /* columnIndex */ )
483 return nullptr;
486 Reference< css::io::XInputStream > BaseResultSet::getCharacterStream( sal_Int32 /* columnIndex */ )
488 return nullptr;
491 Any BaseResultSet::getObject(
492 sal_Int32 /* columnIndex */,
493 const Reference< css::container::XNameAccess >& /* typeMap */ )
495 return Any();
498 Reference< css::sdbc::XRef > BaseResultSet::getRef( sal_Int32 /* columnIndex */ )
500 return Reference< css::sdbc::XRef > ();
503 Reference< css::sdbc::XBlob > BaseResultSet::getBlob( sal_Int32 /* columnIndex */ )
505 return Reference< css::sdbc::XBlob > ();
508 Reference< css::sdbc::XClob > BaseResultSet::getClob( sal_Int32 /* columnIndex */ )
510 return Reference< css::sdbc::XClob > ();
513 Reference< css::sdbc::XArray > BaseResultSet::getArray( sal_Int32 columnIndex )
515 return new Array( m_xMutex, parseArray( getString( columnIndex ) ), *this, m_tc );
518 ::cppu::IPropertyArrayHelper & BaseResultSet::getInfoHelper()
520 return getResultSetPropertyArrayHelper();
523 sal_Bool BaseResultSet::convertFastPropertyValue(
524 Any & /* rConvertedValue */, Any & /* rOldValue */, sal_Int32 nHandle, const Any& rValue )
526 bool bRet;
527 switch( nHandle )
529 case BASERESULTSET_CURSOR_NAME:
531 OUString val;
532 bRet = ( rValue >>= val );
533 m_props[nHandle] <<= val;
534 break;
536 case BASERESULTSET_ESCAPE_PROCESSING:
537 case BASERESULTSET_IS_BOOKMARKABLE:
539 bool val(false);
540 bRet = ( rValue >>= val );
541 m_props[nHandle] <<= val;
542 break;
544 case BASERESULTSET_FETCH_DIRECTION:
545 case BASERESULTSET_FETCH_SIZE:
546 case BASERESULTSET_RESULT_SET_CONCURRENCY:
547 case BASERESULTSET_RESULT_SET_TYPE:
549 sal_Int32 val;
550 bRet = ( rValue >>= val );
551 m_props[nHandle] <<= val;
552 break;
554 default:
556 throw IllegalArgumentException(
557 "pq_resultset: Invalid property handle (" + OUString::number( nHandle ) + ")",
558 *this, 2 );
561 return bRet;
565 void BaseResultSet::setFastPropertyValue_NoBroadcast(
566 sal_Int32 nHandle,const Any& rValue )
568 m_props[nHandle] = rValue;
571 void BaseResultSet::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
573 rValue = m_props[nHandle];
576 Reference < XPropertySetInfo > BaseResultSet::getPropertySetInfo()
578 return OPropertySetHelper::createPropertySetInfo( getResultSetPropertyArrayHelper() );
581 void BaseResultSet::disposing()
583 close();
586 void BaseResultSet::checkColumnIndex(sal_Int32 index )
588 if( index < 1 || index > m_fieldCount )
590 throw SQLException(
591 "pq_resultset: index out of range ("
592 + OUString::number( index )
593 + ", allowed range is 1 to " + OUString::number( m_fieldCount )
594 + ")",
595 *this, OUString(), 1, Any() );
600 void BaseResultSet::checkRowIndex()
602 if( m_row < 0 || m_row >= m_rowCount )
604 throw SQLException(
605 "pq_baseresultset: row index out of range, allowed is 0 to " + OUString::number( m_rowCount -1 )
606 + ", got " + OUString::number( m_row ),
607 *this, OUString(),1, Any() );
613 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */