xref: /AOO41X/main/ucbhelper/source/provider/resultsetmetadata.cxx (revision ac9096f48ddc8269a54878c5b102c19157b971bd)
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