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_connectivity.hxx" 26 27 28 #include "calc/CDatabaseMetaData.hxx" 29 #include "calc/CConnection.hxx" 30 #include <com/sun/star/sdbc/DataType.hpp> 31 #include <com/sun/star/sdbc/ResultSetType.hpp> 32 #include <com/sun/star/sdbc/ColumnValue.hpp> 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 35 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 36 #include <com/sun/star/sdbcx/XIndexesSupplier.hpp> 37 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 38 #include <com/sun/star/sheet/XSpreadsheet.hpp> 39 #include <com/sun/star/sheet/XCellRangesQuery.hpp> 40 #include <com/sun/star/sheet/XCellRangeAddressable.hpp> 41 #include <com/sun/star/sheet/XDatabaseRanges.hpp> 42 #include <com/sun/star/sheet/XDatabaseRange.hpp> 43 #include <tools/urlobj.hxx> 44 #include "FDatabaseMetaDataResultSet.hxx" 45 #include <com/sun/star/lang/XUnoTunnel.hpp> 46 #include <comphelper/types.hxx> 47 #include <rtl/logfile.hxx> 48 49 using namespace connectivity::calc; 50 using namespace connectivity::file; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::beans; 53 using namespace ::com::sun::star::sdbcx; 54 using namespace ::com::sun::star::sdbc; 55 using namespace ::com::sun::star::container; 56 using namespace ::com::sun::star::table; 57 using namespace ::com::sun::star::sheet; 58 59 // ------------------------------------------------------------------------- 60 61 OCalcDatabaseMetaData::OCalcDatabaseMetaData(OConnection* _pCon) :ODatabaseMetaData(_pCon) 62 { 63 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::OCalcDatabaseMetaData" ); 64 } 65 66 // ------------------------------------------------------------------------- 67 68 OCalcDatabaseMetaData::~OCalcDatabaseMetaData() 69 { 70 } 71 72 // ------------------------------------------------------------------------- 73 Reference< XResultSet > OCalcDatabaseMetaData::impl_getTypeInfo_throw( ) 74 { 75 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::impl_getTypeInfo_throw" ); 76 ::osl::MutexGuard aGuard( m_aMutex ); 77 78 ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo); 79 Reference< XResultSet > xRef = pResult; 80 81 static ODatabaseMetaDataResultSet::ORows aRows; 82 if(aRows.empty()) 83 { 84 ODatabaseMetaDataResultSet::ORow aRow; 85 86 aRows.reserve(6); 87 aRow.reserve(18); 88 89 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 90 aRow.push_back(new ORowSetValueDecorator(::rtl::OUString::createFromAscii("VARCHAR"))); 91 aRow.push_back(new ORowSetValueDecorator(DataType::VARCHAR)); 92 aRow.push_back(new ORowSetValueDecorator((sal_Int32)65535)); 93 aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue()); 94 aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue()); 95 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 96 aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); // ORowSetValue((sal_Int32)ColumnValue::NULLABLE) 97 aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); 98 aRow.push_back(new ORowSetValueDecorator((sal_Int32)ColumnSearch::CHAR)); 99 aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); 100 aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); 101 aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); 102 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 103 aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); 104 aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); 105 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 106 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 107 aRow.push_back(new ORowSetValueDecorator((sal_Int32)10)); 108 109 110 aRows.push_back(aRow); 111 112 aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DECIMAL")); 113 aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); 114 aRow[3] = ODatabaseMetaDataResultSet::get0Value(); 115 aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); 116 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); 117 aRows.push_back(aRow); 118 119 aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("BOOL")); 120 aRow[2] = new ORowSetValueDecorator(DataType::BIT); 121 aRow[3] = new ORowSetValueDecorator((sal_Int32)20); 122 aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); 123 aRow[15] = new ORowSetValueDecorator((sal_Int32)15); 124 aRows.push_back(aRow); 125 126 aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DATE")); 127 aRow[2] = new ORowSetValueDecorator(DataType::DATE); 128 aRow[3] = ODatabaseMetaDataResultSet::get0Value(); 129 aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); 130 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); 131 aRows.push_back(aRow); 132 133 aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("TIME")); 134 aRow[2] = new ORowSetValueDecorator(DataType::TIME); 135 aRow[3] = ODatabaseMetaDataResultSet::get0Value(); 136 aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); 137 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); 138 aRows.push_back(aRow); 139 140 aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("TIMESTAMP")); 141 aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP); 142 aRow[3] = ODatabaseMetaDataResultSet::get0Value(); 143 aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); 144 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); 145 aRows.push_back(aRow); 146 } 147 148 pResult->setRows(aRows); 149 return xRef; 150 } 151 152 // ------------------------------------------------------------------------- 153 154 Reference< XResultSet > SAL_CALL OCalcDatabaseMetaData::getColumns( 155 const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, const ::rtl::OUString& tableNamePattern, 156 const ::rtl::OUString& columnNamePattern ) throw(SQLException, RuntimeException) 157 { 158 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getColumns" ); 159 ::osl::MutexGuard aGuard( m_aMutex ); 160 161 162 Reference< XTablesSupplier > xTables = m_pConnection->createCatalog(); 163 if(!xTables.is()) 164 throw SQLException(); 165 166 Reference< XNameAccess> xNames = xTables->getTables(); 167 if(!xNames.is()) 168 throw SQLException(); 169 170 ODatabaseMetaDataResultSet::ORows aRows; 171 ODatabaseMetaDataResultSet::ORow aRow(19); 172 173 aRow[10] = new ORowSetValueDecorator((sal_Int32)10); 174 175 Sequence< ::rtl::OUString> aTabNames(xNames->getElementNames()); 176 const ::rtl::OUString* pTabIter = aTabNames.getConstArray(); 177 const ::rtl::OUString* pTabEnd = pTabIter + aTabNames.getLength(); 178 for(;pTabIter != pTabEnd;++pTabIter) 179 { 180 if(match(tableNamePattern,*pTabIter,'\0')) 181 { 182 const Reference< XColumnsSupplier> xTable(xNames->getByName(*pTabIter),UNO_QUERY_THROW); 183 OSL_ENSURE(xTable.is(),"Table not found! Normallya exception had to be thrown here!"); 184 aRow[3] = new ORowSetValueDecorator(*pTabIter); 185 186 const Reference< XNameAccess> xColumns = xTable->getColumns(); 187 if(!xColumns.is()) 188 throw SQLException(); 189 190 const Sequence< ::rtl::OUString> aColNames(xColumns->getElementNames()); 191 192 const ::rtl::OUString* pColumnIter = aColNames.getConstArray(); 193 const ::rtl::OUString* pEnd = pColumnIter + aColNames.getLength(); 194 Reference< XPropertySet> xColumn; 195 for(sal_Int32 i=1;pColumnIter != pEnd;++pColumnIter,++i) 196 { 197 if(match(columnNamePattern,*pColumnIter,'\0')) 198 { 199 aRow[4] = new ORowSetValueDecorator( *pColumnIter); 200 201 xColumns->getByName(*pColumnIter) >>= xColumn; 202 OSL_ENSURE(xColumn.is(),"Columns contains a column who isn't a fastpropertyset!"); 203 aRow[5] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))); 204 aRow[6] = new ORowSetValueDecorator(::comphelper::getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))); 205 aRow[7] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))); 206 // aRow[8] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)); 207 aRow[9] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))); 208 aRow[11] = new ORowSetValueDecorator(::comphelper::getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))); 209 // aRow[12] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)); 210 aRow[13] = new ORowSetValueDecorator(::comphelper::getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))); 211 // aRow[14] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)); 212 // aRow[15] = xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)); 213 switch(sal_Int32(aRow[5]->getValue())) 214 { 215 case DataType::CHAR: 216 case DataType::VARCHAR: 217 aRow[16] = new ORowSetValueDecorator((sal_Int32)254); 218 break; 219 case DataType::LONGVARCHAR: 220 aRow[16] = new ORowSetValueDecorator((sal_Int32)65535); 221 break; 222 default: 223 aRow[16] = new ORowSetValueDecorator((sal_Int32)0); 224 } 225 aRow[17] = new ORowSetValueDecorator(i); 226 switch(sal_Int32(aRow[11]->getValue())) 227 { 228 case ColumnValue::NO_NULLS: 229 aRow[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("NO")); 230 break; 231 case ColumnValue::NULLABLE: 232 aRow[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("YES")); 233 break; 234 default: 235 aRow[18] = new ORowSetValueDecorator(::rtl::OUString()); 236 } 237 aRows.push_back(aRow); 238 } 239 } 240 } 241 } 242 243 ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eColumns); 244 Reference< XResultSet > xRef = pResult; 245 pResult->setRows(aRows); 246 247 return xRef; 248 } 249 250 // ------------------------------------------------------------------------- 251 252 ::rtl::OUString SAL_CALL OCalcDatabaseMetaData::getURL( ) throw(SQLException, RuntimeException) 253 { 254 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getURL" ); 255 ::osl::MutexGuard aGuard( m_aMutex ); 256 257 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:calc:")) + m_pConnection->getURL(); 258 } 259 260 // ------------------------------------------------------------------------- 261 262 sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxBinaryLiteralLength( ) throw(SQLException, RuntimeException) 263 { 264 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxBinaryLiteralLength" ); 265 return STRING_MAXLEN; 266 } 267 268 // ------------------------------------------------------------------------- 269 270 sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxCharLiteralLength( ) throw(SQLException, RuntimeException) 271 { 272 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxCharLiteralLength" ); 273 return STRING_MAXLEN; 274 } 275 // ------------------------------------------------------------------------- 276 sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnNameLength( ) throw(SQLException, RuntimeException) 277 { 278 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnNameLength" ); 279 return STRING_MAXLEN; 280 } 281 // ------------------------------------------------------------------------- 282 sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnsInIndex( ) throw(SQLException, RuntimeException) 283 { 284 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnsInIndex" ); 285 return 1; 286 } 287 // ------------------------------------------------------------------------- 288 sal_Int32 SAL_CALL OCalcDatabaseMetaData::getMaxColumnsInTable( ) throw(SQLException, RuntimeException) 289 { 290 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getMaxColumnsInTable" ); 291 return 256; 292 } 293 294 // ------------------------------------------------------------------------- 295 296 sal_Bool lcl_IsEmptyOrHidden( const Reference<XSpreadsheets>& xSheets, const ::rtl::OUString& rName ) 297 { 298 Any aAny = xSheets->getByName( rName ); 299 Reference<XSpreadsheet> xSheet; 300 if ( aAny >>= xSheet ) 301 { 302 // test if sheet is hidden 303 304 Reference<XPropertySet> xProp( xSheet, UNO_QUERY ); 305 if (xProp.is()) 306 { 307 sal_Bool bVisible = sal_Bool(); 308 Any aVisAny = xProp->getPropertyValue( ::rtl::OUString::createFromAscii("IsVisible") ); 309 if ( aVisAny >>= bVisible ) 310 if (!bVisible) 311 return sal_True; // hidden 312 } 313 314 #if 0 315 // test if whole sheet is empty 316 317 Reference<XCellRangeAddressable> xAddr( xSheet, UNO_QUERY ); 318 Reference<XCellRangesQuery> xQuery( xSheet, UNO_QUERY ); 319 if ( xAddr.is() && xQuery.is() ) 320 { 321 CellRangeAddress aTotalRange = xAddr->getRangeAddress(); 322 // queryIntersection to get a ranges object 323 Reference<XSheetCellRanges> xRanges = xQuery->queryIntersection( aTotalRange ); 324 if (xRanges.is()) 325 { 326 Reference<XEnumerationAccess> xCells = xRanges->getCells(); 327 if (xCells.is()) 328 { 329 if ( !xCells->hasElements() ) 330 return sal_True; // empty 331 } 332 } 333 } 334 #endif 335 336 // use the same data area as in OCalcTable to test for empty table 337 338 Reference<XSheetCellCursor> xCursor = xSheet->createCursor(); 339 Reference<XCellRangeAddressable> xRange( xCursor, UNO_QUERY ); 340 if ( xRange.is() ) 341 { 342 xCursor->collapseToSize( 1, 1 ); // single (first) cell 343 xCursor->collapseToCurrentRegion(); // contiguous data area 344 345 CellRangeAddress aRangeAddr = xRange->getRangeAddress(); 346 if ( aRangeAddr.StartColumn == aRangeAddr.EndColumn && 347 aRangeAddr.StartRow == aRangeAddr.EndRow ) 348 { 349 // single cell -> check content 350 Reference<XCell> xCell = xCursor->getCellByPosition( 0, 0 ); 351 if ( xCell.is() && xCell->getType() == CellContentType_EMPTY ) 352 return sal_True; 353 } 354 } 355 } 356 357 return sal_False; 358 } 359 360 sal_Bool lcl_IsUnnamed( const Reference<XDatabaseRanges>& xRanges, const ::rtl::OUString& rName ) 361 { 362 sal_Bool bUnnamed = sal_False; 363 364 Any aAny = xRanges->getByName( rName ); 365 Reference<XDatabaseRange> xRange; 366 if ( aAny >>= xRange ) 367 { 368 Reference<XPropertySet> xRangeProp( xRange, UNO_QUERY ); 369 if ( xRangeProp.is() ) 370 { 371 try 372 { 373 Any aUserAny = xRangeProp->getPropertyValue( ::rtl::OUString::createFromAscii("IsUserDefined") ); 374 sal_Bool bUserDefined = sal_Bool(); 375 if ( aUserAny >>= bUserDefined ) 376 bUnnamed = !bUserDefined; 377 } 378 catch ( UnknownPropertyException& ) 379 { 380 // optional property 381 } 382 } 383 } 384 385 return bUnnamed; 386 } 387 388 // ------------------------------------------------------------------------- 389 390 Reference< XResultSet > SAL_CALL OCalcDatabaseMetaData::getTables( 391 const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, 392 const ::rtl::OUString& tableNamePattern, const Sequence< ::rtl::OUString >& types ) 393 throw(SQLException, RuntimeException) 394 { 395 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "calc", "Ocke.Janssen@sun.com", "OCalcDatabaseMetaData::getTables" ); 396 ::osl::MutexGuard aGuard( m_aMutex ); 397 398 ODatabaseMetaDataResultSet* pResult = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables); 399 Reference< XResultSet > xRef = pResult; 400 401 // check if ORowSetValue type is given 402 // when no types are given then we have to return all tables e.g. TABLE 403 404 ::rtl::OUString aTable(::rtl::OUString::createFromAscii("TABLE")); 405 406 sal_Bool bTableFound = sal_True; 407 sal_Int32 nLength = types.getLength(); 408 if(nLength) 409 { 410 bTableFound = sal_False; 411 412 const ::rtl::OUString* pIter = types.getConstArray(); 413 const ::rtl::OUString* pEnd = pIter + nLength; 414 for(;pIter != pEnd;++pIter) 415 { 416 if(*pIter == aTable) 417 { 418 bTableFound = sal_True; 419 break; 420 } 421 } 422 } 423 if(!bTableFound) 424 return xRef; 425 426 // get the sheet names from the document 427 428 OCalcConnection::ODocHolder aDocHodler(((OCalcConnection*)m_pConnection)); 429 Reference<XSpreadsheetDocument> xDoc = aDocHodler.getDoc(); 430 if ( !xDoc.is() ) 431 throw SQLException(); 432 Reference<XSpreadsheets> xSheets = xDoc->getSheets(); 433 if ( !xSheets.is() ) 434 throw SQLException(); 435 Sequence< ::rtl::OUString > aSheetNames = xSheets->getElementNames(); 436 437 ODatabaseMetaDataResultSet::ORows aRows; 438 sal_Int32 nSheetCount = aSheetNames.getLength(); 439 for (sal_Int32 nSheet=0; nSheet<nSheetCount; nSheet++) 440 { 441 ::rtl::OUString aName = aSheetNames[nSheet]; 442 if ( !lcl_IsEmptyOrHidden( xSheets, aName ) && match(tableNamePattern,aName,'\0') ) 443 { 444 ODatabaseMetaDataResultSet::ORow aRow(3); 445 aRow.reserve(6); 446 aRow.push_back(new ORowSetValueDecorator(aName)); 447 aRow.push_back(new ORowSetValueDecorator(aTable)); 448 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 449 aRows.push_back(aRow); 450 } 451 } 452 453 // also use database ranges 454 455 Reference<XPropertySet> xDocProp( xDoc, UNO_QUERY ); 456 if ( xDocProp.is() ) 457 { 458 Any aRangesAny = xDocProp->getPropertyValue( ::rtl::OUString::createFromAscii("DatabaseRanges") ); 459 Reference<XDatabaseRanges> xRanges; 460 if ( aRangesAny >>= xRanges ) 461 { 462 Sequence< ::rtl::OUString > aDBNames = xRanges->getElementNames(); 463 sal_Int32 nDBCount = aDBNames.getLength(); 464 for (sal_Int32 nRange=0; nRange<nDBCount; nRange++) 465 { 466 ::rtl::OUString aName = aDBNames[nRange]; 467 if ( !lcl_IsUnnamed( xRanges, aName ) && match(tableNamePattern,aName,'\0') ) 468 { 469 ODatabaseMetaDataResultSet::ORow aRow(3); 470 aRow.reserve(6); 471 aRow.push_back(new ORowSetValueDecorator(aName)); 472 aRow.push_back(new ORowSetValueDecorator(aTable)); 473 aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); 474 aRows.push_back(aRow); 475 } 476 } 477 } 478 } 479 480 pResult->setRows(aRows); 481 482 return xRef; 483 } 484 // ----------------------------------------------------------------------------- 485 486 487