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 throw( SQLException, RuntimeException )
150 {
151 return m_aProps.getLength();
152 }
153
154 //=========================================================================
155 // virtual
isAutoIncrement(sal_Int32 column)156 sal_Bool SAL_CALL ResultSetMetaData::isAutoIncrement( sal_Int32 column )
157 throw( SQLException, RuntimeException )
158 {
159 /*
160 Checks whether column is automatically numbered, which makes it
161 read-only.
162 */
163
164 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
165 return sal_False;
166
167 return m_pImpl->m_aColumnData[ column - 1 ].isAutoIncrement;
168 }
169
170 //=========================================================================
171 // virtual
isCaseSensitive(sal_Int32 column)172 sal_Bool SAL_CALL ResultSetMetaData::isCaseSensitive( sal_Int32 column )
173 throw( SQLException, RuntimeException )
174 {
175 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
176 return sal_False;
177
178 return m_pImpl->m_aColumnData[ column - 1 ].isCaseSensitive;
179 }
180
181 //=========================================================================
182 // virtual
isSearchable(sal_Int32 column)183 sal_Bool SAL_CALL ResultSetMetaData::isSearchable( sal_Int32 column )
184 throw( SQLException, RuntimeException )
185 {
186 /*
187 Checks whether the value stored in column can be used in a
188 WHERE clause.
189 */
190
191 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
192 return sal_False;
193
194 return m_pImpl->m_aColumnData[ column - 1 ].isSearchable;
195 }
196
197 //=========================================================================
198 // virtual
isCurrency(sal_Int32 column)199 sal_Bool SAL_CALL ResultSetMetaData::isCurrency( sal_Int32 column )
200 throw( SQLException, RuntimeException )
201 {
202 /*
203 Checks whether column is a cash value.
204 */
205
206 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
207 return sal_False;
208
209 return m_pImpl->m_aColumnData[ column - 1 ].isCurrency;
210 }
211
212 //=========================================================================
213 // virtual
isNullable(sal_Int32 column)214 sal_Int32 SAL_CALL ResultSetMetaData::isNullable( sal_Int32 column )
215 throw( SQLException, RuntimeException )
216 {
217 /*
218 Checks whether a NULL can be stored in column.
219 Possible values: see com/sun/star/sdbc/ColumnValue.idl
220 */
221
222 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
223 return ColumnValue::NULLABLE;
224
225 return m_pImpl->m_aColumnData[ column - 1 ].isNullable;
226 }
227
228 //=========================================================================
229 // virtual
isSigned(sal_Int32 column)230 sal_Bool SAL_CALL ResultSetMetaData::isSigned( sal_Int32 column )
231 throw( SQLException, RuntimeException )
232 {
233 /*
234 Checks whether the value stored in column is a signed number.
235 */
236
237 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
238 return sal_False;
239
240 return m_pImpl->m_aColumnData[ column - 1 ].isSigned;
241 }
242
243 //=========================================================================
244 // virtual
getColumnDisplaySize(sal_Int32 column)245 sal_Int32 SAL_CALL ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
246 throw( SQLException, RuntimeException )
247 {
248 /*
249 Gets the normal maximum width in characters for column.
250 */
251
252 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
253 return 16;
254
255 return m_pImpl->m_aColumnData[ column - 1 ].columnDisplaySize;
256 }
257
258 //=========================================================================
259 // virtual
getColumnLabel(sal_Int32 column)260 OUString SAL_CALL ResultSetMetaData::getColumnLabel( sal_Int32 column )
261 throw( SQLException, RuntimeException )
262 {
263 /*
264 Gets the suggested column title for column, to be used in print-
265 outs and displays.
266 */
267
268 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
269 return OUString();
270
271 OUString aLabel = m_pImpl->m_aColumnData[ column - 1 ].columnLabel;
272 if ( aLabel.getLength() )
273 return aLabel;
274
275 return m_aProps.getConstArray()[ column - 1 ].Name;
276 }
277
278 //=========================================================================
279 // virtual
getColumnName(sal_Int32 column)280 OUString SAL_CALL ResultSetMetaData::getColumnName( sal_Int32 column )
281 throw( SQLException, RuntimeException )
282 {
283 /*
284 Gets the name of column.
285 */
286
287 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
288 return OUString();
289
290 return m_aProps.getConstArray()[ column - 1 ].Name;
291 }
292
293 //=========================================================================
294 // virtual
getSchemaName(sal_Int32 column)295 OUString SAL_CALL ResultSetMetaData::getSchemaName( sal_Int32 column )
296 throw( SQLException, RuntimeException )
297 {
298 /*
299 Gets the schema name for the table from which column of this
300 result set was derived.
301 Because this feature is not widely supported, the return value
302 for many DBMSs will be an empty string.
303 */
304
305 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
306 return OUString();
307
308 return m_pImpl->m_aColumnData[ column - 1 ].schemaName;
309 }
310
311 //=========================================================================
312 // virtual
getPrecision(sal_Int32 column)313 sal_Int32 SAL_CALL ResultSetMetaData::getPrecision( sal_Int32 column )
314 throw( SQLException, RuntimeException )
315 {
316 /*
317 For number types, getprecision gets the number of decimal digits
318 in column.
319 For character types, it gets the maximum length in characters for
320 column.
321 For binary types, it gets the maximum length in bytes for column.
322 */
323
324 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
325 return -1;
326
327 return m_pImpl->m_aColumnData[ column - 1 ].precision;
328 }
329
330 //=========================================================================
331 // virtual
getScale(sal_Int32 column)332 sal_Int32 SAL_CALL ResultSetMetaData::getScale( sal_Int32 column )
333 throw( SQLException, RuntimeException )
334 {
335 /*
336 Gets the number of digits to the right of the decimal point for
337 values in column.
338 */
339
340 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
341 return 0;
342
343 return m_pImpl->m_aColumnData[ column - 1 ].scale;
344 }
345
346 //=========================================================================
347 // virtual
getTableName(sal_Int32 column)348 OUString SAL_CALL ResultSetMetaData::getTableName( sal_Int32 column )
349 throw( SQLException, RuntimeException )
350 {
351 /*
352 Gets the name of the table from which column of this result set
353 was derived or "" if there is none (for example, for a join).
354 Because this feature is not widely supported, the return value
355 for many DBMSs will be an empty string.
356 */
357
358 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
359 return OUString();
360
361 return m_pImpl->m_aColumnData[ column - 1 ].tableName;
362 }
363
364 //=========================================================================
365 // virtual
getCatalogName(sal_Int32 column)366 OUString SAL_CALL ResultSetMetaData::getCatalogName( sal_Int32 column )
367 throw( SQLException, RuntimeException )
368 {
369 /*
370 Gets the catalog name for the table from which column of this
371 result set was derived.
372 Because this feature is not widely supported, the return value
373 for many DBMSs will be an empty string.
374 */
375
376 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
377 return OUString();
378
379 return m_pImpl->m_aColumnData[ column - 1 ].catalogName;
380 }
381
382 //=========================================================================
383 // virtual
getColumnType(sal_Int32 column)384 sal_Int32 SAL_CALL ResultSetMetaData::getColumnType( sal_Int32 column )
385 throw( SQLException, RuntimeException )
386 {
387 /*
388 Gets the JDBC type for the value stored in column. ... The STRUCT
389 and DISTINCT type codes are always returned for structured and
390 distinct types, regardless of whether the value will be mapped
391 according to the standard mapping or be a custom mapping.
392 */
393
394 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
395 return DataType::SQLNULL;
396
397 if ( m_aProps.getConstArray()[ column - 1 ].Type
398 == getCppuVoidType() )
399 {
400 // No type given. Try UCB's Properties Manager...
401
402 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
403
404 if ( !m_pImpl->m_bObtainedTypes )
405 {
406 try
407 {
408 Reference< XPropertySetInfo > xInfo(
409 m_xSMgr->createInstance(
410 OUString::createFromAscii(
411 "com.sun.star.ucb.PropertiesManager" ) ),
412 UNO_QUERY );
413 if ( xInfo.is() )
414 {
415 #if 0
416 // Convenient...
417
418 sal_Int32 nCount = m_pImpl->m_aProps.getLength();
419 Property* pProps = m_pImpl->m_aProps.getArray();
420 for ( sal_Int32 n = 0; n < nCount; ++n )
421 {
422 Property& rProp = pProps[ n ];
423
424 try
425 {
426 Property aProp
427 = xInfo->getPropertyByName( rProp.Name );
428 rProp.Type = aProp.Type;
429 }
430 catch ( UnknownPropertyException& )
431 {
432 // getPropertyByName
433 }
434 }
435 #else
436 // Less (remote) calls...
437
438 Sequence< Property > aProps = xInfo->getProperties();
439 const Property* pProps1 = aProps.getConstArray();
440 sal_Int32 nCount1 = aProps.getLength();
441
442 sal_Int32 nCount = m_aProps.getLength();
443 Property* pProps = m_aProps.getArray();
444 for ( sal_Int32 n = 0; n < nCount; ++n )
445 {
446 Property& rProp = pProps[ n ];
447
448 for ( sal_Int32 m = 0; m < nCount1; ++m )
449 {
450 const Property& rProp1 = pProps1[ m ];
451 if ( rProp.Name == rProp1.Name )
452 {
453 // Found...
454 rProp.Type = rProp1.Type;
455 break;
456 }
457 }
458 }
459 #endif
460 }
461 }
462 catch ( RuntimeException& )
463 {
464 throw;
465 }
466 catch ( Exception& )
467 {
468 // createInstance
469 }
470
471 m_pImpl->m_bObtainedTypes = sal_True;
472 }
473 }
474
475 const Type& rType = m_aProps.getConstArray()[ column - 1 ].Type;
476 sal_Int32 nType = DataType::OTHER;
477
478 if ( rType == getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
479 nType = DataType::VARCHAR; // XRow::getString
480 else if ( rType == getCppuBooleanType() )
481 nType = DataType::BIT; // XRow::getBoolean
482 else if ( rType == getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
483 nType = DataType::INTEGER; // XRow::getInt
484 else if ( rType == getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
485 nType = DataType::BIGINT; // XRow::getLong
486 else if ( rType == getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
487 nType = DataType::SMALLINT; // XRow::getShort
488 else if ( rType == getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
489 nType = DataType::TINYINT; // XRow::getByte
490 else if ( rType == getCppuType( static_cast< const float * >( 0 ) ) )
491 nType = DataType::REAL; // XRow::getFloat
492 else if ( rType == getCppuType( static_cast< const double * >( 0 ) ) )
493 nType = DataType::DOUBLE; // XRow::getDouble
494 else if ( rType == getCppuType( static_cast< const Sequence< sal_Int8 > * >( 0 ) ) )
495 nType = DataType::VARBINARY;// XRow::getBytes
496 else if ( rType == getCppuType( static_cast< const Date * >( 0 ) ) )
497 nType = DataType::DATE; // XRow::getDate
498 else if ( rType == getCppuType( static_cast< const Time * >( 0 ) ) )
499 nType = DataType::TIME; // XRow::getTime
500 else if ( rType == getCppuType( static_cast< const DateTime * >( 0 ) ) )
501 nType = DataType::TIMESTAMP;// XRow::getTimestamp
502 else if ( rType == getCppuType( static_cast< Reference< XInputStream > * >( 0 ) ) )
503 nType = DataType::LONGVARBINARY; // XRow::getBinaryStream
504 // nType = DataType::LONGVARCHAR; // XRow::getCharacterStream
505 else if ( rType == getCppuType( static_cast< Reference< XClob > * >( 0 ) ) )
506 nType = DataType::CLOB; // XRow::getClob
507 else if ( rType == getCppuType( static_cast< Reference< XBlob > * >( 0 ) ) )
508 nType = DataType::BLOB; // XRow::getBlob
509 else if ( rType == getCppuType( static_cast< Reference< XArray > * >( 0 ) ) )
510 nType = DataType::ARRAY;// XRow::getArray
511 else if ( rType == getCppuType( static_cast< Reference< XRef > * >( 0 ) ) )
512 nType = DataType::REF;// XRow::getRef
513 else
514 nType = DataType::OBJECT;// XRow::getObject
515
516 return nType;
517 }
518
519 //=========================================================================
520 // virtual
getColumnTypeName(sal_Int32 column)521 OUString SAL_CALL ResultSetMetaData::getColumnTypeName( sal_Int32 column )
522 throw( SQLException, RuntimeException )
523 {
524 /*
525 Gets the type name used by this particular data source for the
526 values stored in column. If the type code for the type of value
527 stored in column is STRUCT, DISTINCT or JAVA_OBJECT, this method
528 returns a fully-qualified SQL type name.
529 */
530
531 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
532 return OUString();
533
534 return m_pImpl->m_aColumnData[ column - 1 ].columnTypeName;
535 }
536
537 //=========================================================================
538 // virtual
isReadOnly(sal_Int32 column)539 sal_Bool SAL_CALL ResultSetMetaData::isReadOnly( sal_Int32 column )
540 throw( SQLException, RuntimeException )
541 {
542 if ( m_pImpl->m_bGlobalReadOnlyValue )
543 return m_bReadOnly;
544
545 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
546 return sal_True;
547
548 // autoincrement==true => readonly
549 return m_pImpl->m_aColumnData[ column - 1 ].isAutoIncrement ||
550 m_pImpl->m_aColumnData[ column - 1 ].isReadOnly;
551 }
552
553 //=========================================================================
554 // virtual
isWritable(sal_Int32 column)555 sal_Bool SAL_CALL ResultSetMetaData::isWritable( sal_Int32 column )
556 throw( SQLException, RuntimeException )
557 {
558 if ( m_pImpl->m_bGlobalReadOnlyValue )
559 return !m_bReadOnly;
560
561 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
562 return sal_False;
563
564 return m_pImpl->m_aColumnData[ column - 1 ].isWritable;
565 }
566
567 //=========================================================================
568 // virtual
isDefinitelyWritable(sal_Int32 column)569 sal_Bool SAL_CALL ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
570 throw( SQLException, RuntimeException )
571 {
572 if ( m_pImpl->m_bGlobalReadOnlyValue )
573 return !m_bReadOnly;
574
575 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
576 return sal_False;
577
578 return m_pImpl->m_aColumnData[ column - 1 ].isDefinitelyWritable;
579 }
580
581 //=========================================================================
582 // virtual
getColumnServiceName(sal_Int32 column)583 OUString SAL_CALL ResultSetMetaData::getColumnServiceName( sal_Int32 column )
584 throw( SQLException, RuntimeException )
585 {
586 /*
587 Returns the fully-qualified name of the service whose instances
588 are manufactured if XResultSet::getObject is called to retrieve
589 a value from the column.
590 */
591
592 if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
593 return OUString();
594
595 return m_pImpl->m_aColumnData[ column - 1 ].columnServiceName;
596 }
597
598 } // namespace ucbhelper
599