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