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 65 ResultSetMetaData_Impl( sal_Int32 nSize ) 66 : m_aColumnData( nSize ), m_bObtainedTypes( sal_False ), 67 m_bGlobalReadOnlyValue( sal_True ) {} 68 69 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 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 //========================================================================= 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 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 148 sal_Int32 SAL_CALL ResultSetMetaData::getColumnCount() 149 throw( SQLException, RuntimeException ) 150 { 151 return m_aProps.getLength(); 152 } 153 154 //========================================================================= 155 // virtual 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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