Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "ResultSet.hxx"
21 : #include "ResultSetMetaData.hxx"
22 : #include "Util.hxx"
23 :
24 : #include <comphelper/sequence.hxx>
25 : #include <cppuhelper/typeprovider.hxx>
26 : #include <cppuhelper/supportsservice.hxx>
27 : #include <connectivity/dbexception.hxx>
28 : #include <propertyids.hxx>
29 : #include <rtl/string.hxx>
30 : #include <rtl/ustrbuf.hxx>
31 : #include <time.h>
32 : #include <TConnection.hxx>
33 :
34 : #include <com/sun/star/beans/PropertyAttribute.hpp>
35 : #include <com/sun/star/lang/DisposedException.hpp>
36 : #include <com/sun/star/sdbc/DataType.hpp>
37 : #include <com/sun/star/sdbcx/CompareBookmark.hpp>
38 :
39 : using namespace ::comphelper;
40 : using namespace ::connectivity;
41 : using namespace ::connectivity::firebird;
42 : using namespace ::cppu;
43 : using namespace ::dbtools;
44 : using namespace ::osl;
45 : using namespace ::rtl;
46 :
47 : using namespace ::com::sun::star;
48 : using namespace ::com::sun::star::uno;
49 : using namespace ::com::sun::star::lang;
50 : using namespace ::com::sun::star::beans;
51 : using namespace ::com::sun::star::sdbc;
52 : using namespace ::com::sun::star::sdbcx;
53 : using namespace ::com::sun::star::container;
54 : using namespace ::com::sun::star::io;
55 : using namespace ::com::sun::star::util;
56 :
57 0 : OResultSet::OResultSet(Connection* pConnection,
58 : ::osl::Mutex& rMutex,
59 : const uno::Reference< XInterface >& xStatement,
60 : isc_stmt_handle& aStatementHandle,
61 : XSQLDA* pSqlda)
62 : : OResultSet_BASE(rMutex)
63 : , OPropertyContainer(OResultSet_BASE::rBHelper)
64 : , m_bIsBookmarkable(false)
65 : , m_nFetchSize(1)
66 : , m_nResultSetType(::com::sun::star::sdbc::ResultSetType::FORWARD_ONLY)
67 : , m_nFetchDirection(::com::sun::star::sdbc::FetchDirection::FORWARD)
68 : , m_nResultSetConcurrency(::com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY)
69 : , m_pConnection(pConnection)
70 : , m_rMutex(rMutex)
71 : , m_xStatement(xStatement)
72 : , m_xMetaData(0)
73 : , m_pSqlda(pSqlda)
74 : , m_statementHandle(aStatementHandle)
75 : , m_bWasNull(false)
76 : , m_currentRow(0)
77 : , m_bIsAfterLastRow(false)
78 0 : , m_fieldCount(pSqlda? pSqlda->sqld : 0)
79 : {
80 : SAL_INFO("connectivity.firebird", "OResultSet().");
81 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE),
82 : PROPERTY_ID_ISBOOKMARKABLE,
83 : PropertyAttribute::READONLY,
84 : &m_bIsBookmarkable,
85 0 : ::getCppuType(&m_bIsBookmarkable));
86 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
87 : PROPERTY_ID_FETCHSIZE,
88 : PropertyAttribute::READONLY,
89 : &m_nFetchSize,
90 0 : ::getCppuType(&m_nFetchSize));
91 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
92 : PROPERTY_ID_RESULTSETTYPE,
93 : PropertyAttribute::READONLY,
94 : &m_nResultSetType,
95 0 : ::getCppuType(&m_nResultSetType));
96 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
97 : PROPERTY_ID_FETCHDIRECTION,
98 : PropertyAttribute::READONLY,
99 : &m_nFetchDirection,
100 0 : ::getCppuType(&m_nFetchDirection));
101 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
102 : PROPERTY_ID_RESULTSETCONCURRENCY,
103 : PropertyAttribute::READONLY,
104 : &m_nResultSetConcurrency,
105 0 : ::getCppuType(&m_nResultSetConcurrency));
106 :
107 0 : if (!pSqlda)
108 0 : return; // TODO: what?
109 :
110 : }
111 :
112 0 : OResultSet::~OResultSet()
113 : {
114 0 : }
115 :
116 : // ---- XResultSet -- Row retrieval methods ------------------------------------
117 0 : sal_Int32 SAL_CALL OResultSet::getRow() throw(SQLException, RuntimeException, std::exception)
118 : {
119 0 : MutexGuard aGuard(m_rMutex);
120 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
121 :
122 0 : return m_currentRow;
123 : }
124 :
125 0 : sal_Bool SAL_CALL OResultSet::next() throw(SQLException, RuntimeException, std::exception)
126 : {
127 0 : MutexGuard aGuard(m_rMutex);
128 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
129 :
130 0 : m_currentRow++;
131 :
132 : ISC_STATUS fetchStat = isc_dsql_fetch(m_statusVector,
133 : &m_statementHandle,
134 : 1,
135 0 : m_pSqlda);
136 0 : if (fetchStat == 0) // SUCCESSFUL
137 : {
138 0 : return sal_True;
139 : }
140 0 : else if (fetchStat == 100L) // END OF DATASET
141 : {
142 0 : m_bIsAfterLastRow = true;
143 0 : return sal_False;
144 : }
145 : else
146 : {
147 : SAL_WARN("connectivity.firebird", "Error when fetching data");
148 : // Throws sql exception as appropriate
149 0 : evaluateStatusVector(m_statusVector, "isc_dsql_fetch", *this);
150 0 : return sal_False;
151 0 : }
152 : }
153 :
154 0 : sal_Bool SAL_CALL OResultSet::previous() throw(SQLException, RuntimeException, std::exception)
155 : {
156 : ::dbtools::throwFunctionNotSupportedException("previous not supported in firebird",
157 0 : *this);
158 0 : return sal_False;
159 : }
160 :
161 0 : sal_Bool SAL_CALL OResultSet::isLast() throw(SQLException, RuntimeException, std::exception)
162 : {
163 : ::dbtools::throwFunctionNotSupportedException("isLast not supported in firebird",
164 0 : *this);
165 0 : return sal_False;
166 : }
167 :
168 0 : sal_Bool SAL_CALL OResultSet::isBeforeFirst() throw(SQLException, RuntimeException, std::exception)
169 : {
170 0 : MutexGuard aGuard(m_rMutex);
171 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
172 :
173 0 : return m_currentRow == 0;
174 : }
175 :
176 0 : sal_Bool SAL_CALL OResultSet::isAfterLast() throw(SQLException, RuntimeException, std::exception)
177 : {
178 0 : MutexGuard aGuard(m_rMutex);
179 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
180 :
181 0 : return m_bIsAfterLastRow;
182 : }
183 :
184 0 : sal_Bool SAL_CALL OResultSet::isFirst() throw(SQLException, RuntimeException, std::exception)
185 : {
186 0 : MutexGuard aGuard(m_rMutex);
187 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
188 :
189 0 : return m_currentRow == 1 && !m_bIsAfterLastRow;
190 : }
191 :
192 0 : void SAL_CALL OResultSet::beforeFirst() throw(SQLException, RuntimeException, std::exception)
193 : {
194 0 : MutexGuard aGuard(m_rMutex);
195 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
196 :
197 0 : if (m_currentRow != 0)
198 : ::dbtools::throwFunctionNotSupportedException("beforeFirst not supported in firebird",
199 0 : *this);
200 0 : }
201 :
202 0 : void SAL_CALL OResultSet::afterLast() throw(SQLException, RuntimeException, std::exception)
203 : {
204 0 : MutexGuard aGuard(m_rMutex);
205 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
206 :
207 0 : if (!m_bIsAfterLastRow)
208 : ::dbtools::throwFunctionNotSupportedException("afterLast not supported in firebird",
209 0 : *this);
210 0 : }
211 :
212 0 : sal_Bool SAL_CALL OResultSet::first() throw(SQLException, RuntimeException, std::exception)
213 : {
214 0 : MutexGuard aGuard(m_rMutex);
215 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
216 :
217 0 : if (m_currentRow == 0)
218 : {
219 0 : return next();
220 : }
221 0 : else if (m_currentRow == 1 && !m_bIsAfterLastRow)
222 : {
223 0 : return sal_True;
224 : }
225 : else
226 : {
227 : ::dbtools::throwFunctionNotSupportedException("first not supported in firebird",
228 0 : *this);
229 0 : return sal_False;
230 0 : }
231 : }
232 :
233 0 : sal_Bool SAL_CALL OResultSet::last() throw(SQLException, RuntimeException, std::exception)
234 : {
235 : // We need to iterate past the last row to know when we've passed the last
236 : // row, hence we can't actually move to last.
237 : ::dbtools::throwFunctionNotSupportedException("last not supported in firebird",
238 0 : *this);
239 0 : return sal_False;
240 : }
241 :
242 0 : sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 aRow) throw(SQLException, RuntimeException, std::exception)
243 : {
244 0 : MutexGuard aGuard(m_rMutex);
245 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
246 :
247 0 : if (aRow > m_currentRow)
248 : {
249 0 : sal_Int32 aIterations = aRow - m_currentRow;
250 0 : return relative(aIterations);
251 : }
252 : else
253 : {
254 : ::dbtools::throwFunctionNotSupportedException("absolute not supported in firebird",
255 0 : *this);
256 0 : return sal_False;
257 0 : }
258 : }
259 :
260 0 : sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row) throw(SQLException, RuntimeException, std::exception)
261 : {
262 0 : MutexGuard aGuard(m_rMutex);
263 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
264 :
265 0 : if (row > 0)
266 : {
267 0 : while (row--)
268 : {
269 0 : if (!next())
270 0 : return sal_False;
271 : }
272 0 : return sal_True;
273 : }
274 : else
275 : {
276 : ::dbtools::throwFunctionNotSupportedException("relative not supported in firebird",
277 0 : *this);
278 0 : return sal_False;
279 0 : }
280 : }
281 :
282 0 : void SAL_CALL OResultSet::checkColumnIndex(sal_Int32 nIndex)
283 : throw (SQLException, RuntimeException)
284 : {
285 0 : MutexGuard aGuard(m_rMutex);
286 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
287 :
288 0 : if( nIndex < 1 || nIndex > m_fieldCount )
289 : {
290 : ::dbtools::throwSQLException(
291 0 : "No column " + OUString::number(nIndex),
292 : ::dbtools::SQL_COLUMN_NOT_FOUND,
293 0 : *this);
294 0 : }
295 0 : }
296 :
297 0 : void SAL_CALL OResultSet::checkRowIndex()
298 : throw (SQLException, RuntimeException)
299 : {
300 0 : MutexGuard aGuard(m_rMutex);
301 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
302 :
303 0 : if((m_currentRow < 1) || m_bIsAfterLastRow)
304 : {
305 : ::dbtools::throwSQLException(
306 : "Invalid Row",
307 : ::dbtools::SQL_INVALID_CURSOR_POSITION,
308 0 : *this);
309 0 : }
310 0 : }
311 :
312 0 : Any SAL_CALL OResultSet::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
313 : {
314 0 : Any aRet = OPropertySetHelper::queryInterface(rType);
315 0 : return aRet.hasValue() ? aRet : OResultSet_BASE::queryInterface(rType);
316 : }
317 :
318 0 : Sequence< Type > SAL_CALL OResultSet::getTypes() throw( RuntimeException, std::exception)
319 : {
320 0 : return concatSequences(OPropertySetHelper::getTypes(), OResultSet_BASE::getTypes());
321 : }
322 : // ---- XColumnLocate ---------------------------------------------------------
323 0 : sal_Int32 SAL_CALL OResultSet::findColumn(const OUString& rColumnName)
324 : throw(SQLException, RuntimeException, std::exception)
325 : {
326 0 : MutexGuard aGuard(m_rMutex);
327 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
328 :
329 0 : uno::Reference< XResultSetMetaData > xMeta = getMetaData();
330 0 : sal_Int32 nLen = xMeta->getColumnCount();
331 : sal_Int32 i;
332 :
333 0 : for(i = 1; i<=nLen; ++i)
334 : {
335 : // We assume case sensitive, otherwise you'd have to test
336 : // xMeta->isCaseSensitive and use qualsIgnoreAsciiCase as needed.
337 0 : if (rColumnName == xMeta->getColumnName(i))
338 0 : return i;
339 : }
340 :
341 0 : ::dbtools::throwInvalidColumnException(rColumnName, *this);
342 : assert(false);
343 0 : return 0; // Never reached
344 : }
345 :
346 0 : uno::Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
347 : {
348 : (void) columnIndex;
349 0 : MutexGuard aGuard(m_rMutex);
350 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
351 :
352 0 : return NULL;
353 : }
354 :
355 0 : uno::Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
356 : {
357 : (void) columnIndex;
358 0 : MutexGuard aGuard(m_rMutex);
359 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
360 :
361 0 : return NULL;
362 : }
363 :
364 : // ---- Internal Utilities ---------------------------------------------------
365 0 : bool OResultSet::isNull(const sal_Int32 nColumnIndex)
366 : {
367 : assert(nColumnIndex <= m_fieldCount);
368 0 : XSQLVAR* pVar = m_pSqlda->sqlvar;
369 :
370 0 : if (pVar[nColumnIndex-1].sqltype & 1) // Indicates column may contain null
371 : {
372 0 : if (*pVar[nColumnIndex-1].sqlind == -1)
373 0 : return true;
374 : }
375 0 : return false;
376 : }
377 :
378 : template <typename T>
379 0 : T OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
380 : {
381 0 : if ((m_bWasNull = isNull(nColumnIndex)))
382 0 : return T();
383 :
384 0 : if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == nType)
385 0 : return *((T*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
386 : else
387 0 : return retrieveValue< ORowSetValue >(nColumnIndex, 0);
388 : }
389 :
390 : template <>
391 0 : ORowSetValue OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
392 : {
393 : // See http://wiki.openoffice.org/wiki/Documentation/DevGuide/Database/Using_the_getXXX_Methods
394 : // (bottom of page) for a chart of possible conversions, we should allow all
395 : // of these -- Blob/Clob will probably need some specialist handling especially
396 : // w.r.t. to generating Strings for them.
397 : //
398 : // Basically we just have to map to the correct direct request and
399 : // ORowSetValue does the rest for us here.
400 0 : switch (m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1)
401 : {
402 : case SQL_TEXT:
403 : case SQL_VARYING:
404 0 : return getString(nColumnIndex);
405 : case SQL_SHORT:
406 0 : return getShort(nColumnIndex);
407 : case SQL_LONG:
408 0 : return getInt(nColumnIndex);
409 : case SQL_FLOAT:
410 0 : return getFloat(nColumnIndex);
411 : case SQL_DOUBLE:
412 0 : return getDouble(nColumnIndex);
413 : case SQL_D_FLOAT:
414 0 : return getFloat(nColumnIndex);
415 : case SQL_TIMESTAMP:
416 0 : return getTimestamp(nColumnIndex);
417 : case SQL_TYPE_TIME:
418 0 : return getTime(nColumnIndex);
419 : case SQL_TYPE_DATE:
420 0 : return getDate(nColumnIndex);
421 : case SQL_INT64:
422 0 : return getLong(nColumnIndex);
423 : case SQL_BLOB:
424 : case SQL_NULL:
425 : case SQL_QUAD:
426 : case SQL_ARRAY:
427 : // TODO: these are all invalid conversions, so maybe we should
428 : // throw an exception?
429 0 : return ORowSetValue();
430 : default:
431 : assert(false);
432 0 : return ORowSetValue();
433 : }
434 : }
435 :
436 : template <>
437 0 : Date OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
438 : {
439 0 : if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TYPE_DATE)
440 : {
441 0 : ISC_DATE aISCDate = *((ISC_DATE*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
442 :
443 : struct tm aCTime;
444 0 : isc_decode_sql_date(&aISCDate, &aCTime);
445 :
446 0 : return Date(aCTime.tm_mday, aCTime.tm_mon, aCTime.tm_year);
447 : }
448 : else
449 : {
450 0 : return retrieveValue< ORowSetValue >(nColumnIndex, 0);
451 : }
452 : }
453 :
454 : template <>
455 0 : Time OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
456 : {
457 0 : if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TYPE_TIME)
458 : {
459 0 : ISC_TIME aISCTime = *((ISC_TIME*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
460 :
461 : struct tm aCTime;
462 0 : isc_decode_sql_time(&aISCTime, &aCTime);
463 :
464 : // first field is nanoseconds -- not supported in firebird or struct tm.
465 : // last field denotes UTC (true) or unknown (false)
466 0 : return Time(0, aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, false);
467 : }
468 : else
469 : {
470 0 : return retrieveValue< ORowSetValue >(nColumnIndex, 0);
471 : }
472 : }
473 :
474 : template <>
475 0 : DateTime OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
476 : {
477 0 : if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TIMESTAMP)
478 : {
479 0 : ISC_TIMESTAMP aISCTimestamp = *((ISC_TIMESTAMP*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
480 :
481 : struct tm aCTime;
482 0 : isc_decode_timestamp(&aISCTimestamp, &aCTime);
483 :
484 : // first field is nanoseconds -- not supported in firebird or struct tm.
485 : // last field denotes UTC (true) or unknown (false)
486 : return DateTime(0, aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, aCTime.tm_mday,
487 0 : aCTime.tm_mon, aCTime.tm_year, false);
488 : }
489 : else
490 : {
491 0 : return retrieveValue< ORowSetValue >(nColumnIndex, 0);
492 : }
493 : }
494 :
495 : template <>
496 0 : OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
497 : {
498 : // &~1 to remove the "can contain NULL" indicator
499 0 : int aSqlType = m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1;
500 0 : if (aSqlType == SQL_TEXT )
501 : {
502 0 : return OUString(m_pSqlda->sqlvar[nColumnIndex-1].sqldata,
503 0 : m_pSqlda->sqlvar[nColumnIndex-1].sqllen,
504 0 : RTL_TEXTENCODING_UTF8);
505 : }
506 0 : else if (aSqlType == SQL_VARYING)
507 : {
508 : // First 2 bytes are a short containing the length of the string
509 : // No idea if sqllen is still valid here?
510 0 : sal_uInt16 aLength = *((sal_uInt16*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
511 0 : return OUString(m_pSqlda->sqlvar[nColumnIndex-1].sqldata + 2,
512 : aLength,
513 0 : RTL_TEXTENCODING_UTF8);
514 : }
515 : else
516 : {
517 0 : return retrieveValue< ORowSetValue >(nColumnIndex, 0);
518 : }
519 : }
520 :
521 : template <>
522 0 : ISC_QUAD* OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
523 : {
524 : // TODO: this is probably wrong
525 0 : if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == nType)
526 0 : return (ISC_QUAD*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata;
527 : else
528 0 : throw SQLException(); // TODO: better exception (can't convert Blob)
529 : }
530 :
531 : template <typename T>
532 0 : T OResultSet::safelyRetrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
533 : {
534 0 : MutexGuard aGuard(m_rMutex);
535 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
536 :
537 0 : checkColumnIndex(nColumnIndex);
538 0 : checkRowIndex();
539 :
540 0 : if ((m_bWasNull = isNull(nColumnIndex)))
541 0 : return T();
542 :
543 0 : return retrieveValue< T >(nColumnIndex, nType);
544 : }
545 :
546 : // ---- XRow -----------------------------------------------------------------
547 0 : sal_Bool SAL_CALL OResultSet::wasNull() throw(SQLException, RuntimeException, std::exception)
548 : {
549 0 : MutexGuard aGuard(m_rMutex);
550 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
551 :
552 0 : return m_bWasNull;
553 : }
554 :
555 : // ---- XRow: Simple Numerical types ------------------------------------------
556 0 : sal_Bool SAL_CALL OResultSet::getBoolean(sal_Int32 nColumnIndex)
557 : throw(SQLException, RuntimeException, std::exception)
558 : {
559 : // Not a native firebird type hence we always have to convert.
560 0 : return safelyRetrieveValue< ORowSetValue >(nColumnIndex);
561 : }
562 :
563 0 : sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 nColumnIndex)
564 : throw(SQLException, RuntimeException, std::exception)
565 : {
566 : // Not a native firebird type hence we always have to convert.
567 0 : return safelyRetrieveValue< ORowSetValue >(nColumnIndex);
568 : }
569 :
570 0 : Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes(sal_Int32 columnIndex)
571 : throw(SQLException, RuntimeException, std::exception)
572 : {
573 : (void) columnIndex;
574 0 : return Sequence< sal_Int8 >(); // TODO: implement
575 : //return safelyRetrieveValue(columnIndex);
576 : }
577 :
578 0 : sal_Int16 SAL_CALL OResultSet::getShort(sal_Int32 columnIndex)
579 : throw(SQLException, RuntimeException, std::exception)
580 : {
581 0 : return safelyRetrieveValue< sal_Int16 >(columnIndex, SQL_SHORT);
582 : }
583 :
584 0 : sal_Int32 SAL_CALL OResultSet::getInt(sal_Int32 columnIndex)
585 : throw(SQLException, RuntimeException, std::exception)
586 : {
587 0 : return safelyRetrieveValue< sal_Int32 >(columnIndex, SQL_LONG);
588 : }
589 :
590 0 : sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 columnIndex)
591 : throw(SQLException, RuntimeException, std::exception)
592 : {
593 0 : return safelyRetrieveValue< sal_Int64 >(columnIndex, SQL_INT64);
594 : }
595 :
596 0 : float SAL_CALL OResultSet::getFloat(sal_Int32 columnIndex)
597 : throw(SQLException, RuntimeException, std::exception)
598 : {
599 0 : return safelyRetrieveValue< float >(columnIndex, SQL_FLOAT);
600 : }
601 :
602 0 : double SAL_CALL OResultSet::getDouble(sal_Int32 columnIndex)
603 : throw(SQLException, RuntimeException, std::exception)
604 : {
605 0 : return safelyRetrieveValue< double >(columnIndex, SQL_DOUBLE);
606 : }
607 :
608 : // ---- XRow: More complex types ----------------------------------------------
609 0 : OUString SAL_CALL OResultSet::getString(sal_Int32 nIndex)
610 : throw(SQLException, RuntimeException, std::exception)
611 : {
612 0 : return safelyRetrieveValue< OUString >(nIndex);
613 : }
614 :
615 0 : Date SAL_CALL OResultSet::getDate(sal_Int32 nIndex)
616 : throw(SQLException, RuntimeException, std::exception)
617 : {
618 0 : return safelyRetrieveValue< Date >(nIndex, SQL_TYPE_DATE);
619 : }
620 :
621 0 : Time SAL_CALL OResultSet::getTime(sal_Int32 nIndex)
622 : throw(SQLException, RuntimeException, std::exception)
623 : {
624 0 : return safelyRetrieveValue< Time >(nIndex, SQL_TYPE_TIME);
625 : }
626 :
627 0 : DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 nIndex)
628 : throw(SQLException, RuntimeException, std::exception)
629 : {
630 0 : return safelyRetrieveValue< DateTime >(nIndex, SQL_TIMESTAMP);
631 : }
632 :
633 :
634 0 : uno::Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData( ) throw(SQLException, RuntimeException, std::exception)
635 : {
636 0 : MutexGuard aGuard(m_rMutex);
637 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
638 :
639 0 : if(!m_xMetaData.is())
640 0 : m_xMetaData = new OResultSetMetaData(m_pConnection, m_pSqlda);
641 0 : return m_xMetaData;
642 : }
643 :
644 0 : uno::Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
645 : {
646 : (void) columnIndex;
647 0 : MutexGuard aGuard(m_rMutex);
648 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
649 :
650 0 : return NULL;
651 : }
652 :
653 :
654 :
655 0 : uno::Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
656 : {
657 : (void) columnIndex;
658 0 : MutexGuard aGuard(m_rMutex);
659 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
660 :
661 0 : return NULL;
662 : }
663 :
664 0 : uno::Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 columnIndex)
665 : throw(SQLException, RuntimeException, std::exception)
666 : {
667 0 : MutexGuard aGuard(m_rMutex);
668 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
669 :
670 : // TODO: CLOB etc. should be valid here too, but we probably want some more
671 : // cleverness around this.
672 0 : ISC_QUAD* pBlobID = safelyRetrieveValue< ISC_QUAD* >(columnIndex, SQL_BLOB);
673 0 : if (!pBlobID)
674 0 : return 0;
675 0 : return m_pConnection->createBlob(pBlobID);
676 : }
677 :
678 :
679 0 : uno::Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
680 : {
681 : (void) columnIndex;
682 0 : MutexGuard aGuard(m_rMutex);
683 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
684 :
685 0 : return NULL;
686 : }
687 :
688 :
689 0 : Any SAL_CALL OResultSet::getObject( sal_Int32 columnIndex, const uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException, std::exception)
690 : {
691 : (void) columnIndex;
692 : (void) typeMap;
693 0 : MutexGuard aGuard(m_rMutex);
694 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
695 :
696 0 : return Any();
697 : }
698 :
699 :
700 :
701 :
702 :
703 0 : void SAL_CALL OResultSet::close() throw(SQLException, RuntimeException, std::exception)
704 : {
705 : SAL_INFO("connectivity.firebird", "close().");
706 :
707 : {
708 0 : MutexGuard aGuard(m_rMutex);
709 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
710 : }
711 0 : dispose();
712 0 : }
713 :
714 :
715 0 : uno::Reference< XInterface > SAL_CALL OResultSet::getStatement()
716 : throw(SQLException, RuntimeException, std::exception)
717 : {
718 0 : MutexGuard aGuard(m_rMutex);
719 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
720 :
721 0 : return m_xStatement;
722 : }
723 : //----- XResultSet: unsupported change detection methods ---------------------
724 0 : sal_Bool SAL_CALL OResultSet::rowDeleted() throw(SQLException, RuntimeException, std::exception)
725 : {
726 : ::dbtools::throwFunctionNotSupportedException("rowDeleted not supported in firebird",
727 0 : *this);
728 0 : return sal_False;
729 : }
730 0 : sal_Bool SAL_CALL OResultSet::rowInserted() throw(SQLException, RuntimeException, std::exception)
731 : {
732 : ::dbtools::throwFunctionNotSupportedException("rowInserted not supported in firebird",
733 0 : *this);
734 0 : return sal_False;
735 : }
736 :
737 0 : sal_Bool SAL_CALL OResultSet::rowUpdated() throw(SQLException, RuntimeException, std::exception)
738 : {
739 : ::dbtools::throwFunctionNotSupportedException("rowUpdated not supported in firebird",
740 0 : *this);
741 0 : return sal_False;
742 : }
743 :
744 0 : void SAL_CALL OResultSet::refreshRow() throw(SQLException, RuntimeException, std::exception)
745 : {
746 : ::dbtools::throwFunctionNotSupportedException("refreshRow not supported in firebird",
747 0 : *this);
748 0 : }
749 :
750 :
751 0 : void SAL_CALL OResultSet::cancel( ) throw(RuntimeException, std::exception)
752 : {
753 0 : MutexGuard aGuard(m_rMutex);
754 0 : checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
755 :
756 0 : }
757 :
758 : //----- XWarningsSupplier UNSUPPORTED -----------------------------------------
759 0 : void SAL_CALL OResultSet::clearWarnings() throw(SQLException, RuntimeException, std::exception)
760 : {
761 : ::dbtools::throwFunctionNotSupportedException("clearWarnings not supported in firebird",
762 0 : *this);
763 0 : }
764 :
765 0 : Any SAL_CALL OResultSet::getWarnings() throw(SQLException, RuntimeException, std::exception)
766 : {
767 : ::dbtools::throwFunctionNotSupportedException("getWarnings not supported in firebird",
768 0 : *this);
769 0 : return Any();
770 : }
771 :
772 : //----- OIdPropertyArrayUsageHelper ------------------------------------------
773 0 : IPropertyArrayHelper* OResultSet::createArrayHelper() const
774 : {
775 0 : Sequence< Property > aProperties;
776 0 : describeProperties(aProperties);
777 0 : return new ::cppu::OPropertyArrayHelper(aProperties);
778 : }
779 :
780 0 : IPropertyArrayHelper & OResultSet::getInfoHelper()
781 : {
782 0 : return *const_cast<OResultSet*>(this)->getArrayHelper();
783 : }
784 :
785 0 : void SAL_CALL OResultSet::acquire() throw()
786 : {
787 0 : OResultSet_BASE::acquire();
788 0 : }
789 :
790 0 : void SAL_CALL OResultSet::release() throw()
791 : {
792 0 : OResultSet_BASE::release();
793 0 : }
794 :
795 0 : uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException, std::exception)
796 : {
797 0 : return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
798 : }
799 :
800 : // ---- XServiceInfo -----------------------------------------------------------
801 0 : OUString SAL_CALL OResultSet::getImplementationName() throw ( RuntimeException, std::exception)
802 : {
803 0 : return OUString("com.sun.star.sdbcx.firebird.ResultSet");
804 : }
805 :
806 0 : Sequence< OUString > SAL_CALL OResultSet::getSupportedServiceNames()
807 : throw( RuntimeException, std::exception)
808 : {
809 0 : Sequence< OUString > aSupported(2);
810 0 : aSupported[0] = "com.sun.star.sdbc.ResultSet";
811 0 : aSupported[1] = "com.sun.star.sdbcx.ResultSet";
812 0 : return aSupported;
813 : }
814 :
815 0 : sal_Bool SAL_CALL OResultSet::supportsService(const OUString& _rServiceName)
816 : throw( RuntimeException, std::exception)
817 : {
818 0 : return cppu::supportsService(this, _rServiceName);
819 : }
820 :
821 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|