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