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