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 :
21 : /**************************************************************************
22 : TODO
23 : **************************************************************************
24 :
25 : *************************************************************************/
26 :
27 : #include "osl/diagnose.h"
28 : #include <com/sun/star/beans/Property.hpp>
29 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
30 : #include <com/sun/star/io/XInputStream.hpp>
31 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 : #include <com/sun/star/sdbc/DataType.hpp>
33 : #include <com/sun/star/sdbc/XArray.hpp>
34 : #include <com/sun/star/sdbc/XBlob.hpp>
35 : #include <com/sun/star/sdbc/XClob.hpp>
36 : #include <com/sun/star/sdbc/XRef.hpp>
37 : #include <com/sun/star/util/Date.hpp>
38 : #include <com/sun/star/util/Time.hpp>
39 : #include <com/sun/star/util/DateTime.hpp>
40 : #include <com/sun/star/ucb/PropertiesManager.hpp>
41 : #include <ucbhelper/resultsetmetadata.hxx>
42 :
43 : using namespace com::sun::star::beans;
44 : using namespace com::sun::star::io;
45 : using namespace com::sun::star::lang;
46 : using namespace com::sun::star::sdbc;
47 : using namespace com::sun::star::ucb;
48 : using namespace com::sun::star::uno;
49 : using namespace com::sun::star::util;
50 :
51 :
52 : namespace ucbhelper_impl {
53 :
54 70 : struct ResultSetMetaData_Impl
55 : {
56 : osl::Mutex m_aMutex;
57 : std::vector< ::ucbhelper::ResultSetColumnData > m_aColumnData;
58 : bool m_bObtainedTypes;
59 : bool m_bGlobalReadOnlyValue;
60 :
61 0 : explicit ResultSetMetaData_Impl( sal_Int32 nSize )
62 : : m_aColumnData( nSize ), m_bObtainedTypes( false ),
63 0 : m_bGlobalReadOnlyValue( true ) {}
64 :
65 70 : explicit ResultSetMetaData_Impl(
66 : const std::vector< ::ucbhelper::ResultSetColumnData >& rColumnData )
67 : : m_aColumnData( rColumnData ), m_bObtainedTypes( false ),
68 70 : m_bGlobalReadOnlyValue( false ) {}
69 : };
70 :
71 : }
72 :
73 : using namespace ucbhelper_impl;
74 :
75 : namespace ucbhelper {
76 :
77 :
78 :
79 :
80 : // ResultSetMetaData Implementation.
81 :
82 :
83 :
84 :
85 0 : ResultSetMetaData::ResultSetMetaData(
86 : const Reference< XComponentContext >& rxContext,
87 : const Sequence< Property >& rProps,
88 : bool bReadOnly )
89 0 : : m_pImpl( new ResultSetMetaData_Impl( rProps.getLength() ) ),
90 : m_xContext( rxContext ),
91 : m_aProps( rProps ),
92 0 : m_bReadOnly( bReadOnly )
93 : {
94 0 : }
95 :
96 :
97 70 : ResultSetMetaData::ResultSetMetaData(
98 : const Reference< XComponentContext >& rxContext,
99 : const Sequence< Property >& rProps,
100 : const std::vector< ResultSetColumnData >& rColumnData )
101 70 : : m_pImpl( new ResultSetMetaData_Impl( rColumnData ) ),
102 : m_xContext( rxContext ),
103 : m_aProps( rProps ),
104 140 : m_bReadOnly( true )
105 : {
106 : OSL_ENSURE( rColumnData.size() == sal_uInt32( rProps.getLength() ),
107 : "ResultSetMetaData ctor - different array sizes!" );
108 70 : }
109 :
110 :
111 : // virtual
112 210 : ResultSetMetaData::~ResultSetMetaData()
113 : {
114 70 : delete m_pImpl;
115 140 : }
116 :
117 :
118 :
119 : // XInterface methods.
120 :
121 70 : void SAL_CALL ResultSetMetaData::acquire()
122 : throw()
123 : {
124 70 : OWeakObject::acquire();
125 70 : }
126 :
127 70 : void SAL_CALL ResultSetMetaData::release()
128 : throw()
129 : {
130 70 : OWeakObject::release();
131 70 : }
132 :
133 0 : css::uno::Any SAL_CALL ResultSetMetaData::queryInterface( const css::uno::Type & rType )
134 : throw( css::uno::RuntimeException, std::exception )
135 : {
136 : css::uno::Any aRet = cppu::queryInterface( rType,
137 : (static_cast< XTypeProvider* >(this)),
138 : (static_cast< XResultSetMetaData* >(this))
139 0 : );
140 0 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
141 : }
142 :
143 : // XTypeProvider methods.
144 :
145 :
146 :
147 0 : XTYPEPROVIDER_IMPL_2( ResultSetMetaData,
148 : XTypeProvider,
149 : XResultSetMetaData );
150 :
151 :
152 :
153 : // XResultSetMetaData methods.
154 :
155 :
156 :
157 : // virtual
158 0 : sal_Int32 SAL_CALL ResultSetMetaData::getColumnCount()
159 : throw( SQLException, RuntimeException, std::exception )
160 : {
161 0 : return m_aProps.getLength();
162 : }
163 :
164 :
165 : // virtual
166 0 : sal_Bool SAL_CALL ResultSetMetaData::isAutoIncrement( sal_Int32 column )
167 : throw( SQLException, RuntimeException, std::exception )
168 : {
169 : /*
170 : Checks whether column is automatically numbered, which makes it
171 : read-only.
172 : */
173 :
174 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
175 0 : return sal_False;
176 :
177 0 : return m_pImpl->m_aColumnData[ column - 1 ].isAutoIncrement;
178 : }
179 :
180 :
181 : // virtual
182 70 : sal_Bool SAL_CALL ResultSetMetaData::isCaseSensitive( sal_Int32 column )
183 : throw( SQLException, RuntimeException, std::exception )
184 : {
185 70 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
186 0 : return sal_False;
187 :
188 70 : return m_pImpl->m_aColumnData[ column - 1 ].isCaseSensitive;
189 : }
190 :
191 :
192 : // virtual
193 0 : sal_Bool SAL_CALL ResultSetMetaData::isSearchable( sal_Int32 column )
194 : throw( SQLException, RuntimeException, std::exception )
195 : {
196 : /*
197 : Checks whether the value stored in column can be used in a
198 : WHERE clause.
199 : */
200 :
201 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
202 0 : return sal_False;
203 :
204 0 : return m_pImpl->m_aColumnData[ column - 1 ].isSearchable;
205 : }
206 :
207 :
208 : // virtual
209 0 : sal_Bool SAL_CALL ResultSetMetaData::isCurrency( sal_Int32 column )
210 : throw( SQLException, RuntimeException, std::exception )
211 : {
212 : /*
213 : Checks whether column is a cash value.
214 : */
215 :
216 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
217 0 : return sal_False;
218 :
219 0 : return m_pImpl->m_aColumnData[ column - 1 ].isCurrency;
220 : }
221 :
222 :
223 : // virtual
224 0 : sal_Int32 SAL_CALL ResultSetMetaData::isNullable( sal_Int32 column )
225 : throw( SQLException, RuntimeException, std::exception )
226 : {
227 : /*
228 : Checks whether a NULL can be stored in column.
229 : Possible values: see com/sun/star/sdbc/ColumnValue.idl
230 : */
231 :
232 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
233 0 : return ColumnValue::NULLABLE;
234 :
235 0 : return m_pImpl->m_aColumnData[ column - 1 ].isNullable;
236 : }
237 :
238 :
239 : // virtual
240 0 : sal_Bool SAL_CALL ResultSetMetaData::isSigned( sal_Int32 column )
241 : throw( SQLException, RuntimeException, std::exception )
242 : {
243 : /*
244 : Checks whether the value stored in column is a signed number.
245 : */
246 :
247 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
248 0 : return sal_False;
249 :
250 0 : return m_pImpl->m_aColumnData[ column - 1 ].isSigned;
251 : }
252 :
253 :
254 : // virtual
255 0 : sal_Int32 SAL_CALL ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
256 : throw( SQLException, RuntimeException, std::exception )
257 : {
258 : /*
259 : Gets the normal maximum width in characters for column.
260 : */
261 :
262 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
263 0 : return 16;
264 :
265 0 : return m_pImpl->m_aColumnData[ column - 1 ].columnDisplaySize;
266 : }
267 :
268 :
269 : // virtual
270 0 : OUString SAL_CALL ResultSetMetaData::getColumnLabel( sal_Int32 column )
271 : throw( SQLException, RuntimeException, std::exception )
272 : {
273 : /*
274 : Gets the suggested column title for column, to be used in print-
275 : outs and displays.
276 : */
277 :
278 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
279 0 : return OUString();
280 :
281 0 : OUString aLabel = m_pImpl->m_aColumnData[ column - 1 ].columnLabel;
282 0 : if ( !aLabel.isEmpty() )
283 0 : return aLabel;
284 :
285 0 : return m_aProps.getConstArray()[ column - 1 ].Name;
286 : }
287 :
288 :
289 : // virtual
290 70 : OUString SAL_CALL ResultSetMetaData::getColumnName( sal_Int32 column )
291 : throw( SQLException, RuntimeException, std::exception )
292 : {
293 : /*
294 : Gets the name of column.
295 : */
296 :
297 70 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
298 0 : return OUString();
299 :
300 70 : return m_aProps.getConstArray()[ column - 1 ].Name;
301 : }
302 :
303 :
304 : // virtual
305 0 : OUString SAL_CALL ResultSetMetaData::getSchemaName( sal_Int32 column )
306 : throw( SQLException, RuntimeException, std::exception )
307 : {
308 : /*
309 : Gets the schema name for the table from which column of this
310 : result set was derived.
311 : Because this feature is not widely supported, the return value
312 : for many DBMSs will be an empty string.
313 : */
314 :
315 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
316 0 : return OUString();
317 :
318 0 : return m_pImpl->m_aColumnData[ column - 1 ].schemaName;
319 : }
320 :
321 :
322 : // virtual
323 0 : sal_Int32 SAL_CALL ResultSetMetaData::getPrecision( sal_Int32 column )
324 : throw( SQLException, RuntimeException, std::exception )
325 : {
326 : /*
327 : For number types, getprecision gets the number of decimal digits
328 : in column.
329 : For character types, it gets the maximum length in characters for
330 : column.
331 : For binary types, it gets the maximum length in bytes for column.
332 : */
333 :
334 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
335 0 : return -1;
336 :
337 0 : return m_pImpl->m_aColumnData[ column - 1 ].precision;
338 : }
339 :
340 :
341 : // virtual
342 0 : sal_Int32 SAL_CALL ResultSetMetaData::getScale( sal_Int32 column )
343 : throw( SQLException, RuntimeException, std::exception )
344 : {
345 : /*
346 : Gets the number of digits to the right of the decimal point for
347 : values in column.
348 : */
349 :
350 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
351 0 : return 0;
352 :
353 0 : return m_pImpl->m_aColumnData[ column - 1 ].scale;
354 : }
355 :
356 :
357 : // virtual
358 0 : OUString SAL_CALL ResultSetMetaData::getTableName( sal_Int32 column )
359 : throw( SQLException, RuntimeException, std::exception )
360 : {
361 : /*
362 : Gets the name of the table from which column of this result set
363 : was derived or "" if there is none (for example, for a join).
364 : Because this feature is not widely supported, the return value
365 : for many DBMSs will be an empty string.
366 : */
367 :
368 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
369 0 : return OUString();
370 :
371 0 : return m_pImpl->m_aColumnData[ column - 1 ].tableName;
372 : }
373 :
374 :
375 : // virtual
376 0 : OUString SAL_CALL ResultSetMetaData::getCatalogName( sal_Int32 column )
377 : throw( SQLException, RuntimeException, std::exception )
378 : {
379 : /*
380 : Gets the catalog name for the table from which column of this
381 : result set was derived.
382 : Because this feature is not widely supported, the return value
383 : for many DBMSs will be an empty string.
384 : */
385 :
386 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
387 0 : return OUString();
388 :
389 0 : return m_pImpl->m_aColumnData[ column - 1 ].catalogName;
390 : }
391 :
392 :
393 : // virtual
394 70 : sal_Int32 SAL_CALL ResultSetMetaData::getColumnType( sal_Int32 column )
395 : throw( SQLException, RuntimeException, std::exception )
396 : {
397 : /*
398 : Gets the JDBC type for the value stored in column. ... The STRUCT
399 : and DISTINCT type codes are always returned for structured and
400 : distinct types, regardless of whether the value will be mapped
401 : according to the standard mapping or be a custom mapping.
402 : */
403 :
404 70 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
405 0 : return DataType::SQLNULL;
406 :
407 140 : if ( m_aProps.getConstArray()[ column - 1 ].Type
408 140 : == cppu::UnoType<void>::get() )
409 : {
410 : // No type given. Try UCB's Properties Manager...
411 :
412 70 : osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
413 :
414 70 : if ( !m_pImpl->m_bObtainedTypes )
415 : {
416 : try
417 : {
418 70 : Reference< XPropertySetInfo > xInfo = PropertiesManager::create( m_xContext );
419 : // Less (remote) calls...
420 :
421 140 : Sequence< Property > aProps = xInfo->getProperties();
422 70 : const Property* pProps1 = aProps.getConstArray();
423 70 : sal_Int32 nCount1 = aProps.getLength();
424 :
425 70 : sal_Int32 nCount = m_aProps.getLength();
426 70 : Property* pProps = m_aProps.getArray();
427 140 : for ( sal_Int32 n = 0; n < nCount; ++n )
428 : {
429 70 : Property& rProp = pProps[ n ];
430 :
431 5810 : for ( sal_Int32 m = 0; m < nCount1; ++m )
432 : {
433 5810 : const Property& rProp1 = pProps1[ m ];
434 5810 : if ( rProp.Name == rProp1.Name )
435 : {
436 : // Found...
437 70 : rProp.Type = rProp1.Type;
438 70 : break;
439 : }
440 : }
441 70 : }
442 : }
443 0 : catch ( RuntimeException& )
444 : {
445 0 : throw;
446 : }
447 0 : catch ( Exception& )
448 : {
449 : // createInstance
450 : }
451 :
452 70 : m_pImpl->m_bObtainedTypes = true;
453 70 : }
454 : }
455 :
456 70 : const Type& rType = m_aProps.getConstArray()[ column - 1 ].Type;
457 70 : sal_Int32 nType = DataType::OTHER;
458 :
459 70 : if ( rType == cppu::UnoType<OUString>::get() )
460 70 : nType = DataType::VARCHAR; // XRow::getString
461 0 : else if ( rType == cppu::UnoType<bool>::get() )
462 0 : nType = DataType::BIT; // XRow::getBoolean
463 0 : else if ( rType == cppu::UnoType<sal_Int32>::get() )
464 0 : nType = DataType::INTEGER; // XRow::getInt
465 0 : else if ( rType == cppu::UnoType<sal_Int64>::get() )
466 0 : nType = DataType::BIGINT; // XRow::getLong
467 0 : else if ( rType == cppu::UnoType<sal_Int16>::get() )
468 0 : nType = DataType::SMALLINT; // XRow::getShort
469 0 : else if ( rType == cppu::UnoType<sal_Int8>::get() )
470 0 : nType = DataType::TINYINT; // XRow::getByte
471 0 : else if ( rType == cppu::UnoType<float>::get() )
472 0 : nType = DataType::REAL; // XRow::getFloat
473 0 : else if ( rType == cppu::UnoType<double>::get() )
474 0 : nType = DataType::DOUBLE; // XRow::getDouble
475 0 : else if ( rType == cppu::UnoType<Sequence<sal_Int8>>::get() )
476 0 : nType = DataType::VARBINARY;// XRow::getBytes
477 0 : else if ( rType == cppu::UnoType<Date>::get() )
478 0 : nType = DataType::DATE; // XRow::getDate
479 0 : else if ( rType == cppu::UnoType<Time>::get() )
480 0 : nType = DataType::TIME; // XRow::getTime
481 0 : else if ( rType == cppu::UnoType<DateTime>::get() )
482 0 : nType = DataType::TIMESTAMP;// XRow::getTimestamp
483 0 : else if ( rType == cppu::UnoType<XInputStream>::get() )
484 0 : nType = DataType::LONGVARBINARY; // XRow::getBinaryStream
485 : // nType = DataType::LONGVARCHAR; // XRow::getCharacterStream
486 0 : else if ( rType == cppu::UnoType<XClob>::get() )
487 0 : nType = DataType::CLOB; // XRow::getClob
488 0 : else if ( rType == cppu::UnoType<XBlob>::get() )
489 0 : nType = DataType::BLOB; // XRow::getBlob
490 0 : else if ( rType == cppu::UnoType<XArray>::get() )
491 0 : nType = DataType::ARRAY;// XRow::getArray
492 0 : else if ( rType == cppu::UnoType<XRef>::get() )
493 0 : nType = DataType::REF;// XRow::getRef
494 : else
495 0 : nType = DataType::OBJECT;// XRow::getObject
496 :
497 70 : return nType;
498 : }
499 :
500 :
501 : // virtual
502 0 : OUString SAL_CALL ResultSetMetaData::getColumnTypeName( sal_Int32 column )
503 : throw( SQLException, RuntimeException, std::exception )
504 : {
505 : /*
506 : Gets the type name used by this particular data source for the
507 : values stored in column. If the type code for the type of value
508 : stored in column is STRUCT, DISTINCT or JAVA_OBJECT, this method
509 : returns a fully-qualified SQL type name.
510 : */
511 :
512 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
513 0 : return OUString();
514 :
515 0 : return m_pImpl->m_aColumnData[ column - 1 ].columnTypeName;
516 : }
517 :
518 :
519 : // virtual
520 0 : sal_Bool SAL_CALL ResultSetMetaData::isReadOnly( sal_Int32 column )
521 : throw( SQLException, RuntimeException, std::exception )
522 : {
523 0 : if ( m_pImpl->m_bGlobalReadOnlyValue )
524 0 : return m_bReadOnly;
525 :
526 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
527 0 : return sal_True;
528 :
529 : // autoincrement==true => readonly
530 0 : return m_pImpl->m_aColumnData[ column - 1 ].isAutoIncrement ||
531 0 : m_pImpl->m_aColumnData[ column - 1 ].isReadOnly;
532 : }
533 :
534 :
535 : // virtual
536 0 : sal_Bool SAL_CALL ResultSetMetaData::isWritable( sal_Int32 column )
537 : throw( SQLException, RuntimeException, std::exception )
538 : {
539 0 : if ( m_pImpl->m_bGlobalReadOnlyValue )
540 0 : return !m_bReadOnly;
541 :
542 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
543 0 : return sal_False;
544 :
545 0 : return m_pImpl->m_aColumnData[ column - 1 ].isWritable;
546 : }
547 :
548 :
549 : // virtual
550 0 : sal_Bool SAL_CALL ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
551 : throw( SQLException, RuntimeException, std::exception )
552 : {
553 0 : if ( m_pImpl->m_bGlobalReadOnlyValue )
554 0 : return !m_bReadOnly;
555 :
556 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
557 0 : return sal_False;
558 :
559 0 : return m_pImpl->m_aColumnData[ column - 1 ].isDefinitelyWritable;
560 : }
561 :
562 :
563 : // virtual
564 0 : OUString SAL_CALL ResultSetMetaData::getColumnServiceName( sal_Int32 column )
565 : throw( SQLException, RuntimeException, std::exception )
566 : {
567 : /*
568 : Returns the fully-qualified name of the service whose instances
569 : are manufactured if XResultSet::getObject is called to retrieve
570 : a value from the column.
571 : */
572 :
573 0 : if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
574 0 : return OUString();
575 :
576 0 : return m_pImpl->m_aColumnData[ column - 1 ].columnServiceName;
577 : }
578 :
579 : } // namespace ucbhelper
580 :
581 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|