1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include "DatabaseMetaData.hxx" 21 #include "Util.hxx" 22 23 #include <ibase.h> 24 #include <rtl/ustrbuf.hxx> 25 #include <sal/log.hxx> 26 #include <FDatabaseMetaDataResultSet.hxx> 27 28 #include <com/sun/star/sdbc/ColumnValue.hpp> 29 #include <com/sun/star/sdbc/DataType.hpp> 30 #include <com/sun/star/sdbc/IndexType.hpp> 31 #include <com/sun/star/sdbc/ResultSetType.hpp> 32 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 33 #include <com/sun/star/sdbc/TransactionIsolation.hpp> 34 #include <com/sun/star/sdbc/XParameters.hpp> 35 #include <com/sun/star/sdbc/XRow.hpp> 36 #include <com/sun/star/sdbc/KeyRule.hpp> 37 #include <com/sun/star/sdbc/Deferrability.hpp> 38 39 using namespace connectivity::firebird; 40 using namespace com::sun::star; 41 using namespace com::sun::star::uno; 42 using namespace com::sun::star::lang; 43 using namespace com::sun::star::beans; 44 using namespace com::sun::star::sdbc; 45 46 ODatabaseMetaData::ODatabaseMetaData(Connection* _pCon) 47 : m_pConnection(_pCon) 48 { 49 SAL_WARN_IF(!m_pConnection.is(), "connectivity.firebird", 50 "ODatabaseMetaData::ODatabaseMetaData: No connection set!"); 51 } 52 53 ODatabaseMetaData::~ODatabaseMetaData() 54 { 55 } 56 57 //----- Catalog Info -- UNSUPPORTED ------------------------------------------- 58 OUString SAL_CALL ODatabaseMetaData::getCatalogSeparator() 59 { 60 return OUString(); 61 } 62 63 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCatalogNameLength() 64 { 65 return -1; 66 } 67 68 OUString SAL_CALL ODatabaseMetaData::getCatalogTerm() 69 { 70 return OUString(); 71 } 72 73 sal_Bool SAL_CALL ODatabaseMetaData::isCatalogAtStart() 74 { 75 return false; 76 } 77 78 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInTableDefinitions() 79 { 80 return false; 81 } 82 83 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInIndexDefinitions() 84 { 85 return false; 86 } 87 88 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInDataManipulation( ) 89 { 90 return false; 91 } 92 93 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCatalogs() 94 { 95 OSL_FAIL("Not implemented yet!"); 96 // TODO implement 97 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCatalogs); 98 } 99 100 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInProcedureCalls() 101 { 102 return false; 103 } 104 105 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions() 106 { 107 return false; 108 } 109 110 //----- Schema Info -- UNSUPPORTED -------------------------------------------- 111 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInProcedureCalls() 112 { 113 return false; 114 } 115 116 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions() 117 { 118 return false; 119 } 120 121 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInDataManipulation() 122 { 123 return false; 124 } 125 126 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInIndexDefinitions() 127 { 128 return false; 129 } 130 131 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInTableDefinitions() 132 { 133 return false; 134 } 135 136 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxSchemaNameLength() 137 { 138 return -1; 139 } 140 141 OUString SAL_CALL ODatabaseMetaData::getSchemaTerm() 142 { 143 return OUString(); 144 } 145 146 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getSchemas() 147 { 148 OSL_FAIL("Not implemented yet!"); 149 // TODO implement 150 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eSchemas); 151 } 152 153 //----- Max Sizes/Lengths ----------------------------------------------------- 154 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxBinaryLiteralLength() 155 { 156 return 32767; 157 } 158 159 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxRowSize() 160 { 161 return 32767; 162 } 163 164 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCharLiteralLength() 165 { 166 return 32767; 167 } 168 169 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnNameLength() 170 { 171 return 31; 172 } 173 174 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInIndex() 175 { 176 // TODO: No idea. 177 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/ 178 return 16; 179 } 180 181 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCursorNameLength() 182 { 183 return 32; 184 } 185 186 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxConnections() 187 { 188 return 100; // Arbitrary 189 } 190 191 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInTable() 192 { 193 // May however be smaller. 194 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/ 195 return 32767; 196 } 197 198 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatementLength() 199 { 200 return 32767; 201 } 202 203 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTableNameLength() 204 { 205 return 31; 206 } 207 208 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTablesInSelect( ) 209 { 210 return 0; // 0 means no limit 211 } 212 213 214 sal_Bool SAL_CALL ODatabaseMetaData::doesMaxRowSizeIncludeBlobs( ) 215 { 216 return false; 217 } 218 219 // ---- Identifiers ----------------------------------------------------------- 220 // Only quoted identifiers are case sensitive, unquoted are case insensitive 221 OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() 222 { 223 OUString aVal('"'); 224 return aVal; 225 } 226 227 sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseQuotedIdentifiers( ) 228 { 229 return true; 230 } 231 232 sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseQuotedIdentifiers() 233 { 234 return false; 235 } 236 237 sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseQuotedIdentifiers() 238 { 239 // TODO: confirm this -- the documentation is highly ambiguous 240 // However it seems this should be true as quoted identifiers ARE 241 // stored mixed case. 242 return true; 243 } 244 245 sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseQuotedIdentifiers() 246 { 247 return false; 248 } 249 250 // ---- Unquoted Identifiers ------------------------------------------------- 251 // All unquoted identifiers are stored upper case. 252 sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseIdentifiers() 253 { 254 return false; 255 } 256 257 sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseIdentifiers() 258 { 259 return false; 260 } 261 262 sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseIdentifiers() 263 { 264 return false; 265 } 266 267 sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseIdentifiers() 268 { 269 return true; 270 } 271 272 // ---- SQL Feature Support --------------------------------------------------- 273 sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar() 274 { 275 return true; 276 } 277 278 sal_Bool SAL_CALL ODatabaseMetaData::supportsMinimumSQLGrammar() 279 { 280 return true; 281 } 282 283 sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithAddColumn() 284 { 285 return true; 286 } 287 288 sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithDropColumn() 289 { 290 return true; 291 } 292 293 sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedDelete() 294 { 295 return true; 296 } 297 298 sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedUpdate() 299 { 300 return true; 301 } 302 303 sal_Bool SAL_CALL ODatabaseMetaData::supportsOuterJoins() 304 { 305 return true; 306 } 307 308 sal_Bool SAL_CALL ODatabaseMetaData::supportsSelectForUpdate() 309 { 310 return true; 311 } 312 313 sal_Bool SAL_CALL ODatabaseMetaData::allTablesAreSelectable() 314 { 315 // TODO: true if embedded, but unsure about remote server 316 return true; 317 } 318 319 sal_Bool SAL_CALL ODatabaseMetaData::supportsConvert(sal_Int32, 320 sal_Int32) 321 { 322 return false; 323 } 324 325 sal_Bool SAL_CALL ODatabaseMetaData::supportsTypeConversion() 326 { 327 return false; 328 } 329 330 sal_Bool SAL_CALL ODatabaseMetaData::supportsColumnAliasing() 331 { 332 return true; 333 } 334 335 sal_Bool SAL_CALL ODatabaseMetaData::supportsTableCorrelationNames() 336 { 337 return true; 338 } 339 340 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxIndexLength( ) 341 { 342 return 0; // 0 means no limit 343 } 344 345 sal_Bool SAL_CALL ODatabaseMetaData::supportsNonNullableColumns( ) 346 { 347 return true; 348 } 349 350 OUString SAL_CALL ODatabaseMetaData::getExtraNameCharacters( ) 351 { 352 return OUString(); 353 } 354 355 sal_Bool SAL_CALL ODatabaseMetaData::supportsDifferentTableCorrelationNames( ) 356 { 357 return false; 358 } 359 // ---- Data definition stuff ------------------------------------------------- 360 sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionIgnoredInTransactions() 361 { 362 return false; 363 } 364 365 sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionCausesTransactionCommit() 366 { 367 return true; 368 } 369 370 sal_Bool SAL_CALL ODatabaseMetaData::supportsDataManipulationTransactionsOnly() 371 { 372 return true; 373 } 374 375 sal_Bool SAL_CALL ODatabaseMetaData:: 376 supportsDataDefinitionAndDataManipulationTransactions() 377 { 378 return false; 379 } 380 //----- Transaction Support -------------------------------------------------- 381 sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactions() 382 { 383 return true; 384 } 385 386 sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossRollback() 387 { 388 return false; 389 } 390 391 sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossCommit() 392 { 393 return false; 394 } 395 396 sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossCommit() 397 { 398 return false; 399 } 400 401 sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossRollback() 402 { 403 return false; 404 } 405 406 sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleTransactions() 407 { 408 return true; 409 } 410 411 sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactionIsolationLevel( 412 sal_Int32 aLevel) 413 { 414 return aLevel == TransactionIsolation::READ_UNCOMMITTED 415 || aLevel == TransactionIsolation::READ_COMMITTED 416 || aLevel == TransactionIsolation::REPEATABLE_READ 417 || aLevel == TransactionIsolation::SERIALIZABLE; 418 } 419 420 sal_Int32 SAL_CALL ODatabaseMetaData::getDefaultTransactionIsolation() 421 { 422 return TransactionIsolation::REPEATABLE_READ; 423 } 424 425 426 sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92FullSQL( ) 427 { 428 return false; 429 } 430 431 sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92EntryLevelSQL( ) 432 { 433 return true; // should be supported at least 434 } 435 436 sal_Bool SAL_CALL ODatabaseMetaData::supportsIntegrityEnhancementFacility( ) 437 { 438 return true; 439 } 440 441 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatements( ) 442 { 443 return 0; // 0 means no limit 444 } 445 446 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxProcedureNameLength( ) 447 { 448 return 31; // TODO: confirm 449 } 450 451 sal_Bool SAL_CALL ODatabaseMetaData::allProceduresAreCallable( ) 452 { 453 return false; 454 } 455 456 sal_Bool SAL_CALL ODatabaseMetaData::supportsStoredProcedures( ) 457 { 458 return true; 459 } 460 461 sal_Bool SAL_CALL ODatabaseMetaData::isReadOnly( ) 462 { 463 return m_pConnection->isReadOnly(); 464 } 465 466 sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFiles( ) 467 { 468 return m_pConnection->isEmbedded(); 469 } 470 471 sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFilePerTable( ) 472 { 473 return false; 474 } 475 476 sal_Bool SAL_CALL ODatabaseMetaData::nullPlusNonNullIsNull( ) 477 { 478 return false; 479 } 480 481 sal_Bool SAL_CALL ODatabaseMetaData::supportsExpressionsInOrderBy( ) 482 { 483 return false; 484 } 485 486 sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupBy( ) 487 { 488 return true; 489 } 490 491 sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByBeyondSelect( ) 492 { 493 // Unsure 494 return true; 495 } 496 497 sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByUnrelated( ) 498 { 499 // Unsure 500 return false; 501 } 502 503 504 sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets( ) 505 { 506 return false; 507 } 508 509 sal_Bool SAL_CALL ODatabaseMetaData::supportsLikeEscapeClause( ) 510 { 511 return false; 512 } 513 514 sal_Bool SAL_CALL ODatabaseMetaData::supportsOrderByUnrelated( ) 515 { 516 return false; 517 } 518 519 sal_Bool SAL_CALL ODatabaseMetaData::supportsUnion( ) 520 { 521 return true; 522 } 523 524 sal_Bool SAL_CALL ODatabaseMetaData::supportsUnionAll( ) 525 { 526 return true; 527 } 528 529 sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtEnd( ) 530 { 531 return false; 532 } 533 534 sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtStart( ) 535 { 536 return false; 537 } 538 539 sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedHigh( ) 540 { 541 return false; 542 } 543 544 sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedLow( ) 545 { 546 return false; 547 } 548 549 sal_Bool SAL_CALL ODatabaseMetaData::supportsCorrelatedSubqueries( ) 550 { 551 return false; 552 } 553 554 sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInComparisons( ) 555 { 556 return false; 557 } 558 559 sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInExists( ) 560 { 561 return false; 562 } 563 564 sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInIns( ) 565 { 566 return false; 567 } 568 569 sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInQuantifieds( ) 570 { 571 return false; 572 } 573 574 sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92IntermediateSQL( ) 575 { 576 return false; 577 } 578 579 OUString SAL_CALL ODatabaseMetaData::getURL() 580 { 581 return m_pConnection->getConnectionURL(); 582 } 583 584 OUString SAL_CALL ODatabaseMetaData::getUserName( ) 585 { 586 return OUString(); 587 } 588 589 OUString SAL_CALL ODatabaseMetaData::getDriverName( ) 590 { 591 return OUString(); 592 } 593 594 OUString SAL_CALL ODatabaseMetaData::getDriverVersion() 595 { 596 return OUString(); 597 } 598 599 OUString SAL_CALL ODatabaseMetaData::getDatabaseProductVersion( ) 600 { 601 uno::Reference< XStatement > xSelect = m_pConnection->createStatement(); 602 603 uno::Reference< XResultSet > xRs = xSelect->executeQuery("SELECT rdb$get_context('SYSTEM', 'ENGINE_VERSION') as version from rdb$database"); 604 xRs->next(); // first and only row 605 uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW ); 606 return xRow->getString(1); 607 } 608 609 OUString SAL_CALL ODatabaseMetaData::getDatabaseProductName( ) 610 { 611 return "Firebird (engine12)"; 612 } 613 614 OUString SAL_CALL ODatabaseMetaData::getProcedureTerm( ) 615 { 616 return OUString(); 617 } 618 619 sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMajorVersion( ) 620 { 621 return 1; 622 } 623 624 sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMinorVersion( ) 625 { 626 return 0; 627 } 628 629 OUString SAL_CALL ODatabaseMetaData::getSQLKeywords( ) 630 { 631 return OUString(); 632 } 633 634 OUString SAL_CALL ODatabaseMetaData::getSearchStringEscape( ) 635 { 636 return OUString(); 637 } 638 639 OUString SAL_CALL ODatabaseMetaData::getStringFunctions( ) 640 { 641 return "ASCII_CHAR,ASCII_VAL,BIT_LENGTH,CHAR_LENGTH,CHAR_TO_UUID,CHARACTER_LENGTH," 642 "GEN_UUID,HASH,LEFT,LOWER,LPAD,OCTET_LENGTH,OVERLAY,POSITION,REPLACE,REVERSE," 643 "RIGHT,RPAD,SUBSTRING,TRIM,UPPER,UUID_TO_CHAR"; 644 } 645 646 OUString SAL_CALL ODatabaseMetaData::getTimeDateFunctions( ) 647 { 648 return "CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,DATEADD, DATEDIFF," 649 "EXTRACT,'NOW','TODAY','TOMORROW','YESTERDAY'"; 650 } 651 652 OUString SAL_CALL ODatabaseMetaData::getSystemFunctions( ) 653 { 654 return OUString(); 655 } 656 657 OUString SAL_CALL ODatabaseMetaData::getNumericFunctions( ) 658 { 659 return "ABS,ACOS,ASIN,ATAN,ATAN2,BIN_AND,BIN_NOT,BIN_OR,BIN_SHL," 660 "BIN_SHR,BIN_XOR,CEIL,CEILING,COS,COSH,COT,EXP,FLOOR,LN," 661 "LOG,LOG10,MOD,PI,POWER,RAND,ROUND,SIGN,SIN,SINH,SQRT,TAN,TANH,TRUNC"; 662 } 663 664 sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar( ) 665 { 666 return false; 667 } 668 669 sal_Bool SAL_CALL ODatabaseMetaData::supportsFullOuterJoins( ) 670 { 671 return false; 672 } 673 674 sal_Bool SAL_CALL ODatabaseMetaData::supportsLimitedOuterJoins( ) 675 { 676 return false; 677 } 678 679 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInGroupBy( ) 680 { 681 return 0; // 0 means no limit 682 } 683 684 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInOrderBy( ) 685 { 686 return 0; // 0 means no limit 687 } 688 689 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInSelect( ) 690 { 691 return 0; // 0 means no limit 692 } 693 694 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxUserNameLength( ) 695 { 696 return 31; 697 } 698 699 sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetType(sal_Int32 setType) 700 { 701 switch (setType) 702 { 703 case ResultSetType::FORWARD_ONLY: 704 return true; 705 default: 706 return false; 707 } 708 } 709 710 sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetConcurrency( 711 sal_Int32 aResultSetType, 712 sal_Int32 aConcurrency) 713 { 714 if (aResultSetType == ResultSetType::FORWARD_ONLY 715 && aConcurrency == ResultSetConcurrency::READ_ONLY) 716 return true; 717 else 718 return false; 719 } 720 721 sal_Bool SAL_CALL ODatabaseMetaData::ownUpdatesAreVisible( sal_Int32 ) 722 { 723 return false; 724 } 725 726 sal_Bool SAL_CALL ODatabaseMetaData::ownDeletesAreVisible( sal_Int32 ) 727 { 728 return false; 729 } 730 731 sal_Bool SAL_CALL ODatabaseMetaData::ownInsertsAreVisible( sal_Int32 ) 732 { 733 return false; 734 } 735 736 sal_Bool SAL_CALL ODatabaseMetaData::othersUpdatesAreVisible( sal_Int32 ) 737 { 738 return false; 739 } 740 741 sal_Bool SAL_CALL ODatabaseMetaData::othersDeletesAreVisible( sal_Int32 ) 742 { 743 return false; 744 } 745 746 sal_Bool SAL_CALL ODatabaseMetaData::othersInsertsAreVisible( sal_Int32 ) 747 { 748 return false; 749 } 750 751 sal_Bool SAL_CALL ODatabaseMetaData::updatesAreDetected( sal_Int32 ) 752 { 753 return false; 754 } 755 756 sal_Bool SAL_CALL ODatabaseMetaData::deletesAreDetected( sal_Int32 ) 757 { 758 return false; 759 } 760 761 sal_Bool SAL_CALL ODatabaseMetaData::insertsAreDetected( sal_Int32 ) 762 { 763 return false; 764 } 765 766 sal_Bool SAL_CALL ODatabaseMetaData::supportsBatchUpdates() 767 { 768 // No batch support in firebird 769 return false; 770 } 771 772 uno::Reference< XConnection > SAL_CALL ODatabaseMetaData::getConnection() 773 { 774 return uno::Reference<XConnection>(m_pConnection.get()); 775 } 776 777 // here follow all methods which return a resultset 778 // the first methods is an example implementation how to use this resultset 779 // of course you could implement it on your and you should do this because 780 // the general way is more memory expensive 781 782 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTableTypes( ) 783 { 784 ODatabaseMetaDataResultSet* pResultSet = new 785 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTableTypes); 786 uno::Reference< XResultSet > xResultSet = pResultSet; 787 788 ODatabaseMetaDataResultSet::ORows aResults; 789 ODatabaseMetaDataResultSet::ORow aRow(2); 790 791 aRow[0] = new ORowSetValueDecorator(); // unused 792 793 // TODO Put these statics to one place 794 // like postgreSQL's Statics class. 795 796 aRow[1] = new ORowSetValueDecorator(OUString("TABLE")); 797 aResults.push_back(aRow); 798 799 aRow[1] = new ORowSetValueDecorator(OUString("VIEW")); 800 aResults.push_back(aRow); 801 802 aRow[1] = new ORowSetValueDecorator(OUString("SYSTEM TABLE")); 803 aResults.push_back(aRow); 804 805 pResultSet->setRows(aResults); 806 return xResultSet; 807 } 808 809 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() 810 { 811 SAL_INFO("connectivity.firebird", "getTypeInfo()"); 812 813 // this returns an empty resultset where the column-names are already set 814 // in special the metadata of the resultset already returns the right columns 815 ODatabaseMetaDataResultSet* pResultSet = 816 new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTypeInfo); 817 uno::Reference< XResultSet > xResultSet = pResultSet; 818 static ODatabaseMetaDataResultSet::ORows aResults = []() 819 { 820 ODatabaseMetaDataResultSet::ORows tmp; 821 ODatabaseMetaDataResultSet::ORow aRow(19); 822 823 // Common data 824 aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue(); // Literal quote marks 825 aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue(); // Literal quote marks 826 aRow[7] = new ORowSetValueDecorator(true); // Nullable 827 aRow[8] = new ORowSetValueDecorator(true); // Case sensitive 828 aRow[10] = new ORowSetValueDecorator(false); // Is unsigned 829 // FIXED_PREC_SCALE: docs state "can it be a money value? " however 830 // in reality this causes Base to treat all numbers as money formatted 831 // by default which is wrong (and formatting as money value is still 832 // possible for all values). 833 aRow[11] = new ORowSetValueDecorator(false); 834 // Localised Type Name -- TODO: implement (but can be null): 835 aRow[13] = new ORowSetValueDecorator(); 836 aRow[16] = new ORowSetValueDecorator(); // Unused 837 aRow[17] = new ORowSetValueDecorator(); // Unused 838 aRow[18] = new ORowSetValueDecorator(sal_Int16(10));// Radix 839 840 // Char 841 aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); 842 aRow[2] = new ORowSetValueDecorator(DataType::CHAR); 843 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 844 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 845 aRow[9] = new ORowSetValueDecorator( 846 sal_Int16(ColumnSearch::FULL)); // Searchable 847 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 848 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 849 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 850 tmp.push_back(aRow); 851 852 // Varchar 853 aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); 854 aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR); 855 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 856 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 857 aRow[9] = new ORowSetValueDecorator( 858 sal_Int16(ColumnSearch::FULL)); // Searchable 859 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 860 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 861 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 862 tmp.push_back(aRow); 863 864 // Binary (CHAR) 865 // It is distinguished from Text type by its character set 866 aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); 867 aRow[2] = new ORowSetValueDecorator(DataType::BINARY); 868 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 869 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 870 aRow[9] = new ORowSetValueDecorator( 871 sal_Int16(ColumnSearch::NONE)); // Searchable 872 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 873 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 874 tmp.push_back(aRow); 875 876 // Varbinary (VARCHAR) 877 aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); 878 aRow[2] = new ORowSetValueDecorator(DataType::VARBINARY); 879 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 880 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 881 aRow[9] = new ORowSetValueDecorator( 882 sal_Int16(ColumnSearch::NONE)); // Searchable 883 884 // Clob (SQL_BLOB) 885 aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); // BLOB, with subtype 1 886 aRow[2] = new ORowSetValueDecorator(DataType::CLOB); 887 aRow[3] = new ORowSetValueDecorator(sal_Int32(2147483647)); // Precision = max length 888 aRow[6] = new ORowSetValueDecorator(); // Create Params 889 aRow[9] = new ORowSetValueDecorator( 890 sal_Int16(ColumnSearch::FULL)); // Searchable 891 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 892 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 893 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 894 tmp.push_back(aRow); 895 896 // Longvarbinary (SQL_BLOB) 897 // Distinguished from simple blob with a user-defined subtype. 898 aRow[2] = new ORowSetValueDecorator(DataType::LONGVARBINARY); 899 tmp.push_back(aRow); 900 901 // Integer Types common 902 { 903 aRow[6] = new ORowSetValueDecorator(); // Create Params 904 aRow[9] = new ORowSetValueDecorator( 905 sal_Int16(ColumnSearch::FULL)); // Searchable 906 aRow[12] = new ORowSetValueDecorator(true); // Autoincrement 907 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 908 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 909 } 910 // Smallint (SQL_SHORT) 911 aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT")); 912 aRow[2] = new ORowSetValueDecorator(DataType::SMALLINT); 913 aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision 914 tmp.push_back(aRow); 915 // Integer (SQL_LONG) 916 aRow[1] = new ORowSetValueDecorator(OUString("INTEGER")); 917 aRow[2] = new ORowSetValueDecorator(DataType::INTEGER); 918 aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision 919 tmp.push_back(aRow); 920 // Bigint (SQL_INT64) 921 aRow[1] = new ORowSetValueDecorator(OUString("BIGINT")); 922 aRow[2] = new ORowSetValueDecorator(DataType::BIGINT); 923 aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision 924 tmp.push_back(aRow); 925 926 // Decimal Types common 927 { 928 aRow[9] = new ORowSetValueDecorator( 929 sal_Int16(ColumnSearch::FULL)); // Searchable 930 aRow[12] = new ORowSetValueDecorator(true); // Autoincrement 931 } 932 933 aRow[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params 934 // Numeric 935 aRow[1] = new ORowSetValueDecorator(OUString("NUMERIC")); 936 aRow[2] = new ORowSetValueDecorator(DataType::NUMERIC); 937 aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision 938 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 939 aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale 940 tmp.push_back(aRow); 941 // Decimal 942 aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL")); 943 aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); 944 aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision 945 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 946 aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale 947 tmp.push_back(aRow); 948 949 aRow[6] = new ORowSetValueDecorator(); // Create Params 950 // Float (SQL_FLOAT) 951 aRow[1] = new ORowSetValueDecorator(OUString("FLOAT")); 952 aRow[2] = new ORowSetValueDecorator(DataType::FLOAT); 953 aRow[3] = new ORowSetValueDecorator(sal_Int16(7)); // Precision 954 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 955 aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale 956 tmp.push_back(aRow); 957 // Double (SQL_DOUBLE) 958 aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION")); 959 aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE); 960 aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision 961 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 962 aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale 963 tmp.push_back(aRow); 964 965 // TODO: no idea whether D_FLOAT corresponds to an sql type 966 967 // SQL_TIMESTAMP 968 aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP")); 969 aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP); 970 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 971 aRow[6] = new ORowSetValueDecorator(); // Create Params 972 aRow[9] = new ORowSetValueDecorator( 973 sal_Int16(ColumnSearch::FULL)); // Searchable 974 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 975 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 976 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 977 tmp.push_back(aRow); 978 979 // SQL_TYPE_TIME 980 aRow[1] = new ORowSetValueDecorator(OUString("TIME")); 981 aRow[2] = new ORowSetValueDecorator(DataType::TIME); 982 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 983 aRow[6] = new ORowSetValueDecorator(); // Create Params 984 aRow[9] = new ORowSetValueDecorator( 985 sal_Int16(ColumnSearch::FULL)); // Searchable 986 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 987 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 988 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 989 tmp.push_back(aRow); 990 991 // SQL_TYPE_DATE 992 aRow[1] = new ORowSetValueDecorator(OUString("DATE")); 993 aRow[2] = new ORowSetValueDecorator(DataType::DATE); 994 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 995 aRow[6] = new ORowSetValueDecorator(); // Create Params 996 aRow[9] = new ORowSetValueDecorator( 997 sal_Int16(ColumnSearch::FULL)); // Searchable 998 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 999 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1000 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1001 tmp.push_back(aRow); 1002 1003 // SQL_BLOB 1004 aRow[1] = new ORowSetValueDecorator(OUString("BLOB")); 1005 aRow[2] = new ORowSetValueDecorator(DataType::BLOB); 1006 aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length 1007 aRow[6] = new ORowSetValueDecorator(); // Create Params 1008 aRow[9] = new ORowSetValueDecorator( 1009 sal_Int16(ColumnSearch::NONE)); // Searchable 1010 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 1011 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1012 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1013 tmp.push_back(aRow); 1014 1015 // SQL_BOOLEAN 1016 aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN")); 1017 aRow[2] = new ORowSetValueDecorator(DataType::BOOLEAN); 1018 aRow[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length 1019 aRow[6] = new ORowSetValueDecorator(); // Create Params 1020 aRow[9] = new ORowSetValueDecorator( 1021 sal_Int16(ColumnSearch::BASIC)); // Searchable 1022 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 1023 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1024 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1025 tmp.push_back(aRow); 1026 return tmp; 1027 }(); 1028 pResultSet->setRows(aResults); 1029 return xResultSet; 1030 } 1031 1032 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumnPrivileges( 1033 const Any& /*aCatalog*/, 1034 const OUString& /*sSchema*/, 1035 const OUString& sTable, 1036 const OUString& sColumnNamePattern) 1037 { 1038 SAL_INFO("connectivity.firebird", "getColumnPrivileges() with " 1039 "Table: " << sTable 1040 << " & ColumnNamePattern: " << sColumnNamePattern); 1041 1042 ODatabaseMetaDataResultSet* pResultSet = new 1043 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumnPrivileges); 1044 uno::Reference< XResultSet > xResultSet = pResultSet; 1045 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1046 1047 static const char wld[] = "%"; 1048 OUStringBuffer queryBuf( 1049 "SELECT " 1050 "priv.RDB$RELATION_NAME, " // 1 Table name 1051 "priv.RDB$GRANTOR," // 2 1052 "priv.RDB$USER, " // 3 Grantee 1053 "priv.RDB$PRIVILEGE, " // 4 1054 "priv.RDB$GRANT_OPTION, " // 5 is Grantable 1055 "priv.RDB$FIELD_NAME " // 6 Column name 1056 "FROM RDB$USER_PRIVILEGES priv "); 1057 1058 { 1059 OUString sAppend = "WHERE priv.RDB$RELATION_NAME = '%' "; 1060 queryBuf.append(sAppend.replaceAll("%", sTable)); 1061 } 1062 if (!sColumnNamePattern.isEmpty()) 1063 { 1064 OUString sAppend; 1065 if (sColumnNamePattern.match(wld)) 1066 sAppend = "AND priv.RDB$FIELD_NAME LIKE '%' "; 1067 else 1068 sAppend = "AND priv.RDB$FIELD_NAME = '%' "; 1069 1070 queryBuf.append(sAppend.replaceAll(wld, sColumnNamePattern)); 1071 } 1072 1073 queryBuf.append(" ORDER BY priv.RDB$FIELD, " 1074 "priv.RDB$PRIVILEGE"); 1075 1076 OUString query = queryBuf.makeStringAndClear(); 1077 1078 uno::Reference< XResultSet > rs = statement->executeQuery(query.getStr()); 1079 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1080 ODatabaseMetaDataResultSet::ORows aResults; 1081 1082 ODatabaseMetaDataResultSet::ORow aCurrentRow(9); 1083 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused 1084 aCurrentRow[1] = new ORowSetValueDecorator(); // 1. TABLE_CAT Unsupported 1085 aCurrentRow[2] = new ORowSetValueDecorator(); // 1. TABLE_SCHEM Unsupported 1086 1087 while( rs->next() ) 1088 { 1089 // 3. TABLE_NAME 1090 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1091 // 4. COLUMN_NAME 1092 aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(6))); 1093 aCurrentRow[5] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); // 5. GRANTOR 1094 aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(3))); // 6. GRANTEE 1095 aCurrentRow[7] = new ORowSetValueDecorator(xRow->getString(4)); // 7. Privilege 1096 aCurrentRow[8] = new ORowSetValueDecorator( ( xRow->getShort(5) == 1 ) ? 1097 OUString("YES") : OUString("NO")); // 8. Grantable 1098 1099 aResults.push_back(aCurrentRow); 1100 } 1101 1102 pResultSet->setRows( aResults ); 1103 1104 return xResultSet; 1105 } 1106 1107 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns( 1108 const Any& /*catalog*/, 1109 const OUString& /*schemaPattern*/, 1110 const OUString& tableNamePattern, 1111 const OUString& columnNamePattern) 1112 { 1113 SAL_INFO("connectivity.firebird", "getColumns() with " 1114 "TableNamePattern: " << tableNamePattern << 1115 " & ColumnNamePattern: " << columnNamePattern); 1116 1117 OUStringBuffer queryBuf("SELECT " 1118 "relfields.RDB$RELATION_NAME, " // 1 1119 "relfields.RDB$FIELD_NAME, " // 2 1120 "relfields.RDB$DESCRIPTION," // 3 1121 "relfields.RDB$DEFAULT_VALUE, " // 4 1122 "relfields.RDB$FIELD_POSITION, "// 5 1123 "fields.RDB$FIELD_TYPE, " // 6 1124 "fields.RDB$FIELD_SUB_TYPE, " // 7 1125 "fields.RDB$FIELD_LENGTH, " // 8 1126 "fields.RDB$FIELD_PRECISION, " // 9 1127 "fields.RDB$FIELD_SCALE, " // 10 1128 // Specifically use relfields null flag -- the one in fields is used 1129 // for domains, whether a specific field is nullable is set in relfields, 1130 // this is also the one we manually fiddle when changing NULL/NOT NULL 1131 // (see Table.cxx) 1132 "relfields.RDB$NULL_FLAG, " // 11 1133 "fields.RDB$CHARACTER_LENGTH, " // 12 1134 "charset.RDB$CHARACTER_SET_NAME " // 13 1135 "FROM RDB$RELATION_FIELDS relfields " 1136 "JOIN RDB$FIELDS fields " 1137 "on (fields.RDB$FIELD_NAME = relfields.RDB$FIELD_SOURCE) " 1138 "LEFT JOIN RDB$CHARACTER_SETS charset " 1139 "on (fields.RDB$CHARACTER_SET_ID = charset.RDB$CHARACTER_SET_ID) " 1140 "WHERE (1 = 1) "); 1141 1142 if (!tableNamePattern.isEmpty()) 1143 { 1144 OUString sAppend; 1145 if (tableNamePattern.match("%")) 1146 sAppend = "AND relfields.RDB$RELATION_NAME LIKE '%' "; 1147 else 1148 sAppend = "AND relfields.RDB$RELATION_NAME = '%' "; 1149 1150 queryBuf.append(sAppend.replaceAll("%", tableNamePattern)); 1151 } 1152 1153 if (!columnNamePattern.isEmpty()) 1154 { 1155 OUString sAppend; 1156 if (columnNamePattern.match("%")) 1157 sAppend = "AND relfields.RDB$FIELD_NAME LIKE '%' "; 1158 else 1159 sAppend = "AND relfields.RDB$FIELD_NAME = '%' "; 1160 1161 queryBuf.append(sAppend.replaceAll("%", columnNamePattern)); 1162 } 1163 1164 OUString query = queryBuf.makeStringAndClear(); 1165 1166 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1167 uno::Reference< XResultSet > rs = statement->executeQuery(query.getStr()); 1168 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1169 1170 ODatabaseMetaDataResultSet::ORows aResults; 1171 ODatabaseMetaDataResultSet::ORow aCurrentRow(19); 1172 1173 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0 1174 aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null 1175 aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null 1176 aCurrentRow[8] = new ORowSetValueDecorator(); // Unused 1177 aCurrentRow[10] = new ORowSetValueDecorator(sal_Int32(10)); // Radix: fixed in FB 1178 aCurrentRow[14] = new ORowSetValueDecorator(); // Unused 1179 aCurrentRow[15] = new ORowSetValueDecorator(); // Unused 1180 1181 while( rs->next() ) 1182 { 1183 // 3. TABLE_NAME 1184 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1185 // 4. Column Name 1186 aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); 1187 // 5. Datatype 1188 short aType = getFBTypeFromBlrType(xRow->getShort(6)); 1189 short aScale = xRow->getShort(10); 1190 OUString sCharsetName = xRow->getString(13); 1191 // result field may be filled with spaces 1192 sCharsetName = sCharsetName.trim(); 1193 ColumnTypeInfo aInfo(aType, xRow->getShort(7), aScale, 1194 xRow->getString(13)); 1195 1196 aCurrentRow[5] = new ORowSetValueDecorator(aInfo.getSdbcType()); 1197 // 6. Typename (SQL_*) 1198 aCurrentRow[6] = new ORowSetValueDecorator(aInfo.getColumnTypeName()); 1199 1200 // 7. Column Sizes 1201 { 1202 sal_Int32 aColumnSize = 0; 1203 switch (aType) 1204 { 1205 case SQL_TEXT: 1206 case SQL_VARYING: 1207 aColumnSize = xRow->getShort(12); 1208 break; 1209 case SQL_SHORT: 1210 case SQL_LONG: 1211 case SQL_FLOAT: 1212 case SQL_DOUBLE: 1213 case SQL_D_FLOAT: 1214 case SQL_INT64: 1215 case SQL_QUAD: 1216 aColumnSize = xRow->getShort(9); 1217 break; 1218 case SQL_TIMESTAMP: 1219 case SQL_BLOB: 1220 case SQL_ARRAY: 1221 case SQL_TYPE_TIME: 1222 case SQL_TYPE_DATE: 1223 case SQL_NULL: 1224 // TODO: implement. 1225 break; 1226 } 1227 aCurrentRow[7] = new ORowSetValueDecorator(aColumnSize); 1228 } 1229 1230 // 9. Decimal digits (scale) 1231 // fb stores a negative number 1232 aCurrentRow[9] = new ORowSetValueDecorator( static_cast<sal_Int16>(-aScale) ); 1233 1234 // 11. Nullable 1235 if (xRow->getShort(11)) 1236 { 1237 aCurrentRow[11] = new ORowSetValueDecorator(ColumnValue::NO_NULLS); 1238 } 1239 else 1240 { 1241 aCurrentRow[11] = new ORowSetValueDecorator(ColumnValue::NULLABLE); 1242 } 1243 // 12. Comments -- may be omitted 1244 { 1245 OUString aDescription; 1246 uno::Reference< XBlob > xDescriptionBlob = xRow->getBlob(3); 1247 if (xDescriptionBlob.is()) 1248 { 1249 sal_Int32 aBlobLength = static_cast<sal_Int32>(xDescriptionBlob->length()); 1250 aDescription = OUString(reinterpret_cast<char*>(xDescriptionBlob->getBytes(0, aBlobLength).getArray()), 1251 aBlobLength, 1252 RTL_TEXTENCODING_UTF8); 1253 } 1254 aCurrentRow[12] = new ORowSetValueDecorator(aDescription); 1255 } 1256 // 13. Default -- may be omitted. 1257 { 1258 uno::Reference< XBlob > xDefaultValueBlob = xRow->getBlob(4); 1259 if (xDefaultValueBlob.is()) 1260 { 1261 // TODO: Implement 1262 } 1263 aCurrentRow[13] = new ORowSetValueDecorator(); 1264 } 1265 1266 // 16. Bytes in Column for char 1267 if (aType == SQL_TEXT) 1268 { 1269 aCurrentRow[16] = new ORowSetValueDecorator(xRow->getShort(8)); 1270 } 1271 else if (aType == SQL_VARYING) 1272 { 1273 aCurrentRow[16] = new ORowSetValueDecorator(sal_Int32(32767)); 1274 } 1275 else 1276 { 1277 aCurrentRow[16] = new ORowSetValueDecorator(sal_Int32(0)); 1278 } 1279 // 17. Index of column 1280 { 1281 short nColumnNumber = xRow->getShort(5); 1282 // Firebird stores column numbers beginning with 0 internally 1283 // SDBC expects column numbering to begin with 1. 1284 aCurrentRow[17] = new ORowSetValueDecorator(sal_Int32(nColumnNumber + 1)); 1285 } 1286 // 18. Is nullable 1287 if (xRow->getShort(9)) 1288 { 1289 aCurrentRow[18] = new ORowSetValueDecorator(OUString("NO")); 1290 } 1291 else 1292 { 1293 aCurrentRow[18] = new ORowSetValueDecorator(OUString("YES")); 1294 } 1295 1296 aResults.push_back(aCurrentRow); 1297 } 1298 ODatabaseMetaDataResultSet* pResultSet = new 1299 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumns); 1300 uno::Reference< XResultSet > xResultSet = pResultSet; 1301 pResultSet->setRows( aResults ); 1302 1303 return xResultSet; 1304 } 1305 1306 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTables( 1307 const Any& /*catalog*/, 1308 const OUString& /*schemaPattern*/, 1309 const OUString& tableNamePattern, 1310 const Sequence< OUString >& types) 1311 { 1312 SAL_INFO("connectivity.firebird", "getTables() with " 1313 "TableNamePattern: " << tableNamePattern); 1314 1315 ODatabaseMetaDataResultSet* pResultSet = new 1316 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables); 1317 uno::Reference< XResultSet > xResultSet = pResultSet; 1318 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1319 1320 static const char wld[] = "%"; 1321 OUStringBuffer queryBuf( 1322 "SELECT " 1323 "RDB$RELATION_NAME, " 1324 "RDB$SYSTEM_FLAG, " 1325 "RDB$RELATION_TYPE, " 1326 "RDB$DESCRIPTION, " 1327 "RDB$VIEW_BLR " 1328 "FROM RDB$RELATIONS " 1329 "WHERE "); 1330 1331 // TODO: GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM 1332 if (!types.hasElements() || (types.getLength() == 1 && types[0].match(wld))) 1333 { 1334 // All table types? I.e. includes system tables. 1335 queryBuf.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1) "); 1336 } 1337 else 1338 { 1339 queryBuf.append("( (0 = 1) "); 1340 for (int i = 0; i < types.getLength(); i++) 1341 { 1342 if (types[i] == "SYSTEM TABLE") 1343 queryBuf.append("OR (RDB$SYSTEM_FLAG = 1 AND RDB$VIEW_BLR IS NULL) "); 1344 else if (types[i] == "TABLE") 1345 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NULL) "); 1346 else if (types[i] == "VIEW") 1347 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NOT NULL) "); 1348 else 1349 throw SQLException(); // TODO: implement other types, see above. 1350 } 1351 queryBuf.append(") "); 1352 } 1353 1354 if (!tableNamePattern.isEmpty()) 1355 { 1356 OUString sAppend; 1357 if (tableNamePattern.match(wld)) 1358 sAppend = "AND RDB$RELATION_NAME LIKE '%' "; 1359 else 1360 sAppend = "AND RDB$RELATION_NAME = '%' "; 1361 1362 queryBuf.append(sAppend.replaceAll(wld, tableNamePattern)); 1363 } 1364 1365 queryBuf.append(" ORDER BY RDB$RELATION_TYPE, RDB$RELATION_NAME"); 1366 1367 OUString query = queryBuf.makeStringAndClear(); 1368 1369 uno::Reference< XResultSet > rs = statement->executeQuery(query.getStr()); 1370 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1371 ODatabaseMetaDataResultSet::ORows aResults; 1372 1373 ODatabaseMetaDataResultSet::ORow aCurrentRow(6); 1374 aCurrentRow[0] = new ORowSetValueDecorator(); // 0. Unused 1375 aCurrentRow[1] = new ORowSetValueDecorator(); // 1. Table_Cat Unsupported 1376 aCurrentRow[2] = new ORowSetValueDecorator(); // 2. Table_Schem Unsupported 1377 1378 while( rs->next() ) 1379 { 1380 // 3. TABLE_NAME 1381 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1382 // 4. TABLE_TYPE 1383 { 1384 // TODO: check this as the docs are a bit unclear. 1385 sal_Int16 nSystemFlag = xRow->getShort(2); 1386 sal_Int16 nTableType = xRow->getShort(3); 1387 xRow->getBlob(5); // We have to retrieve a column to verify it is null. 1388 bool aIsView = !xRow->wasNull(); 1389 OUString sTableType; 1390 1391 if (nSystemFlag == 1) 1392 { 1393 sTableType = "SYSTEM TABLE"; 1394 } 1395 else if (aIsView) 1396 { 1397 sTableType = "VIEW"; 1398 } 1399 else 1400 { 1401 if (nTableType == 0) 1402 sTableType = "TABLE"; 1403 } 1404 1405 aCurrentRow[4] = new ORowSetValueDecorator(sTableType); 1406 } 1407 // 5. REMARKS 1408 { 1409 uno::Reference< XBlob > xBlob = xRow->getBlob(4); 1410 OUString sDescription; 1411 1412 if (xBlob.is()) 1413 { 1414 // TODO: we should actually be using CLOB here instead. 1415 // However we haven't implemented CLOB yet, so use BLOB. 1416 sal_Int32 aBlobLength = static_cast<sal_Int32>(xBlob->length()); 1417 sDescription = OUString(reinterpret_cast<char*>(xBlob->getBytes(0, aBlobLength).getArray()), 1418 aBlobLength, 1419 RTL_TEXTENCODING_UTF8); 1420 } 1421 1422 aCurrentRow[5] = new ORowSetValueDecorator(sDescription); 1423 } 1424 1425 aResults.push_back(aCurrentRow); 1426 } 1427 1428 pResultSet->setRows( aResults ); 1429 1430 return xResultSet; 1431 } 1432 1433 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedureColumns( 1434 const Any&, const OUString&, 1435 const OUString&, const OUString& ) 1436 { 1437 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1438 OSL_FAIL("Not implemented yet!"); 1439 // TODO implement 1440 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedureColumns); 1441 } 1442 1443 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedures( 1444 const Any&, const OUString&, 1445 const OUString& ) 1446 { 1447 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1448 OSL_FAIL("Not implemented yet!"); 1449 // TODO implement 1450 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedures); 1451 } 1452 1453 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getVersionColumns( 1454 const Any&, const OUString&, const OUString& ) 1455 { 1456 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1457 OSL_FAIL("Not implemented yet!"); 1458 // TODO implement 1459 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eVersionColumns); 1460 } 1461 1462 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getExportedKeys( 1463 const Any&, const OUString&, const OUString& ) 1464 { 1465 // List the columns in a table which are foreign keys. This is actually 1466 // never used anywhere in the LO codebase currently. Retrieval from firebird 1467 // requires using a 5-table join. 1468 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1469 OSL_FAIL("Not implemented yet!"); 1470 // TODO implement 1471 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eExportedKeys); 1472 } 1473 1474 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getImportedKeys( 1475 const Any&, const OUString&, const OUString& table ) 1476 { 1477 ODatabaseMetaDataResultSet* pResultSet = new 1478 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eImportedKeys); 1479 uno::Reference< XResultSet > xResultSet = pResultSet; 1480 1481 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1482 1483 OUString sSQL = "SELECT " 1484 "RDB$REF_CONSTRAINTS.RDB$UPDATE_RULE, " // 1 update rule 1485 "RDB$REF_CONSTRAINTS.RDB$DELETE_RULE, " // 2 delete rule 1486 "RDB$REF_CONSTRAINTS.RDB$CONST_NAME_UQ, " // 3 primary or unique key name 1487 "RDB$REF_CONSTRAINTS.RDB$CONSTRAINT_NAME, " // 4 foreign key name 1488 "PRIM.RDB$DEFERRABLE, " // 5 deferrability 1489 "PRIM.RDB$INITIALLY_DEFERRED, " // 6 deferrability 1490 "PRIM.RDB$RELATION_NAME, " // 7 PK table name 1491 "PRIMARY_INDEX.RDB$FIELD_NAME, " // 8 PK column name 1492 "PRIMARY_INDEX.RDB$FIELD_POSITION, " // 9 PK sequence number 1493 "FOREI.RDB$RELATION_NAME, " // 10 FK table name 1494 "FOREIGN_INDEX.RDB$FIELD_NAME " // 11 FK column name 1495 "FROM RDB$REF_CONSTRAINTS " 1496 "INNER JOIN RDB$RELATION_CONSTRAINTS AS PRIM " 1497 "ON RDB$REF_CONSTRAINTS.RDB$CONST_NAME_UQ = PRIM.RDB$CONSTRAINT_NAME " 1498 "INNER JOIN RDB$RELATION_CONSTRAINTS AS FOREI " 1499 "ON RDB$REF_CONSTRAINTS.RDB$CONSTRAINT_NAME = FOREI.RDB$CONSTRAINT_NAME " 1500 "INNER JOIN RDB$INDEX_SEGMENTS AS PRIMARY_INDEX " 1501 "ON PRIM.RDB$INDEX_NAME = PRIMARY_INDEX.RDB$INDEX_NAME " 1502 "INNER JOIN RDB$INDEX_SEGMENTS AS FOREIGN_INDEX " 1503 "ON FOREI.RDB$INDEX_NAME = FOREIGN_INDEX.RDB$INDEX_NAME " 1504 "WHERE FOREI.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY' " 1505 "AND FOREI.RDB$RELATION_NAME = '"+ table +"'"; 1506 1507 uno::Reference< XResultSet > rs = statement->executeQuery(sSQL); 1508 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1509 1510 ODatabaseMetaDataResultSet::ORows aResults; 1511 ODatabaseMetaDataResultSet::ORow aCurrentRow(15); 1512 1513 // TODO is it necessary to initialize these? 1514 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused 1515 aCurrentRow[1] = new ORowSetValueDecorator(); // PKTABLE_CAT unsupported 1516 aCurrentRow[2] = new ORowSetValueDecorator(); // PKTABLE_SCHEM unsupported 1517 aCurrentRow[5] = new ORowSetValueDecorator(); // FKTABLE_CAT unsupported 1518 aCurrentRow[6] = new ORowSetValueDecorator(); // FKTABLE_SCHEM unsupported 1519 1520 std::map< OUString,sal_Int32> aRuleMap; 1521 aRuleMap[ OUString("CASCADE")] = KeyRule::CASCADE; 1522 aRuleMap[ OUString("RESTRICT")] = KeyRule::RESTRICT; 1523 aRuleMap[ OUString("SET NULL")] = KeyRule::SET_NULL; 1524 aRuleMap[ OUString("SET DEFAULT")] = KeyRule::SET_DEFAULT; 1525 aRuleMap[ OUString("NO ACTION")] = KeyRule::NO_ACTION; 1526 1527 while(rs->next()) 1528 { 1529 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(7))); // PK table 1530 aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(8))); // PK column 1531 aCurrentRow[7] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(10))); // FK table 1532 aCurrentRow[8] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(11))); // FK column 1533 1534 aCurrentRow[9] = new ORowSetValueDecorator(xRow->getShort(9)); // PK sequence number 1535 aCurrentRow[10] = new ORowSetValueDecorator(aRuleMap[sanitizeIdentifier(xRow->getString(1))]); // update role 1536 aCurrentRow[11] = new ORowSetValueDecorator(aRuleMap[sanitizeIdentifier(xRow->getString(2))]); // delete role 1537 1538 aCurrentRow[12] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4))); // FK name 1539 aCurrentRow[13] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(3))); // PK name 1540 1541 aCurrentRow[14] = new ORowSetValueDecorator(Deferrability::NONE); // deferrability 1542 1543 // deferrability is currently not supported, but may be supported in the future. 1544 /* 1545 aCurrentRow[14] = (xRow->getString(5) == "NO" ? 1546 new ORowSetValueDecorator(Deferrability::NONE) 1547 : (xRow->getString(6) == "NO" ? 1548 new ORowSetValueDecorator(Deferrability::INITIALLY_IMMEDIATE) 1549 : new ORowSetValueDecorator(Deferrability::INITIALLY_DEFERRED)); 1550 */ 1551 1552 aResults.push_back(aCurrentRow); 1553 } 1554 1555 pResultSet->setRows( aResults ); 1556 return xResultSet; 1557 } 1558 1559 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getPrimaryKeys( 1560 const Any& /*aCatalog*/, 1561 const OUString& /*sSchema*/, 1562 const OUString& sTable) 1563 { 1564 SAL_INFO("connectivity.firebird", "getPrimaryKeys() with " 1565 "Table: " << sTable); 1566 1567 OUStringBuffer aQueryBuf("SELECT " 1568 "constr.RDB$RELATION_NAME, " // 1. Table Name 1569 "inds.RDB$FIELD_NAME, " // 2. Column Name 1570 "inds.RDB$FIELD_POSITION, " // 3. Sequence Number 1571 "constr.RDB$CONSTRAINT_NAME " // 4 Constraint name 1572 "FROM RDB$RELATION_CONSTRAINTS constr " 1573 "JOIN RDB$INDEX_SEGMENTS inds " 1574 "on (constr.RDB$INDEX_NAME = inds.RDB$INDEX_NAME) "); 1575 1576 OUString sAppend = "WHERE constr.RDB$RELATION_NAME = '%' "; 1577 aQueryBuf.append(sAppend.replaceAll("%", sTable)); 1578 1579 aQueryBuf.append("AND constr.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " 1580 "ORDER BY inds.RDB$FIELD_NAME"); 1581 1582 OUString sQuery = aQueryBuf.makeStringAndClear(); 1583 1584 uno::Reference< XStatement > xStatement = m_pConnection->createStatement(); 1585 uno::Reference< XResultSet > xRs = xStatement->executeQuery(sQuery); 1586 uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW ); 1587 1588 ODatabaseMetaDataResultSet::ORows aResults; 1589 ODatabaseMetaDataResultSet::ORow aCurrentRow(7); 1590 1591 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0 1592 aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null 1593 aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null 1594 1595 while(xRs->next()) 1596 { 1597 // 3. Table Name 1598 if (xRs->getRow() == 1) // Table name doesn't change, so only retrieve once 1599 { 1600 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1601 } 1602 // 4. Column Name 1603 aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); 1604 // 5. KEY_SEQ (which key in the sequence) 1605 aCurrentRow[5] = new ORowSetValueDecorator(xRow->getShort(3)); 1606 // 6. Primary Key Name 1607 aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4))); 1608 1609 aResults.push_back(aCurrentRow); 1610 } 1611 ODatabaseMetaDataResultSet* pResultSet = new 1612 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys); 1613 uno::Reference< XResultSet > xResultSet = pResultSet; 1614 pResultSet->setRows( aResults ); 1615 1616 return xResultSet; 1617 } 1618 1619 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getIndexInfo( 1620 const Any& /*aCatalog*/, 1621 const OUString& /*sSchema*/, 1622 const OUString& sTable, 1623 sal_Bool bIsUnique, 1624 sal_Bool) // TODO: what is bIsApproximate? 1625 1626 { 1627 // Apparently this method can also return a "tableIndexStatistic" 1628 // However this is only mentioned in XDatabaseMetaData.idl (whose comments 1629 // are duplicated in the postgresql driver), and is otherwise undocumented. 1630 SAL_INFO("connectivity.firebird", "getPrimaryKeys() with " 1631 "Table: " << sTable); 1632 1633 OUStringBuffer aQueryBuf("SELECT " 1634 "indices.RDB$RELATION_NAME, " // 1. Table Name 1635 "index_segments.RDB$FIELD_NAME, " // 2. Column Name 1636 "index_segments.RDB$FIELD_POSITION, " // 3. Sequence Number 1637 "indices.RDB$INDEX_NAME, " // 4. Index name 1638 "indices.RDB$UNIQUE_FLAG, " // 5. Unique Flag 1639 "indices.RDB$INDEX_TYPE " // 6. Index Type 1640 "FROM RDB$INDICES indices " 1641 "JOIN RDB$INDEX_SEGMENTS index_segments " 1642 "on (indices.RDB$INDEX_NAME = index_segments.RDB$INDEX_NAME) " 1643 "WHERE indices.RDB$RELATION_NAME = '" + sTable + "' " 1644 "AND (indices.RDB$SYSTEM_FLAG = 0) "); 1645 // Not sure whether we should exclude system indices, but otoh. we never 1646 // actually deal with system tables (system indices only apply to system 1647 // tables) within the GUI. 1648 1649 // Only filter if true (according to the docs), i.e.: 1650 // If false we return all indices, if true we return only unique indices 1651 if (bIsUnique) 1652 aQueryBuf.append("AND (indices.RDB$UNIQUE_FLAG = 1) "); 1653 1654 OUString sQuery = aQueryBuf.makeStringAndClear(); 1655 1656 uno::Reference< XStatement > xStatement = m_pConnection->createStatement(); 1657 uno::Reference< XResultSet > xRs = xStatement->executeQuery(sQuery); 1658 uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW ); 1659 1660 ODatabaseMetaDataResultSet::ORows aResults; 1661 ODatabaseMetaDataResultSet::ORow aCurrentRow(14); 1662 1663 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0 1664 aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null 1665 aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null 1666 aCurrentRow[5] = new ORowSetValueDecorator(); // Index Catalog -- can be null 1667 // According to wikipedia firebird uses clustered indices. 1668 // The documentation does not specifically seem to specify this. 1669 aCurrentRow[7] = new ORowSetValueDecorator(IndexType::CLUSTERED); // 7. INDEX TYPE 1670 aCurrentRow[13] = new ORowSetValueDecorator(); // Filter Condition -- can be null 1671 1672 while(xRs->next()) 1673 { 1674 // 3. Table Name 1675 if (xRs->getRow() == 1) // Table name doesn't change, so only retrieve once 1676 { 1677 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1678 } 1679 1680 // 4. NON_UNIQUE -- i.e. specifically negate here. 1681 aCurrentRow[4] = new ORowSetValueDecorator(xRow->getShort(5) == 0); 1682 // 6. INDEX NAME 1683 aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4))); 1684 1685 // 8. ORDINAL POSITION 1686 aCurrentRow[8] = new ORowSetValueDecorator(xRow->getShort(3)); 1687 // 9. COLUMN NAME 1688 aCurrentRow[9] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); 1689 // 10. ASC(ending)/DESC(ending) 1690 if (xRow->getShort(6) == 1) 1691 aCurrentRow[10] = new ORowSetValueDecorator(OUString("D")); 1692 else 1693 aCurrentRow[10] = new ORowSetValueDecorator(OUString("A")); 1694 // TODO: double check this^^^, doesn't seem to be officially documented anywhere. 1695 // 11. CARDINALITY 1696 aCurrentRow[11] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this 1697 // 12. PAGES 1698 aCurrentRow[12] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this 1699 1700 aResults.push_back(aCurrentRow); 1701 } 1702 ODatabaseMetaDataResultSet* pResultSet = new 1703 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys); 1704 uno::Reference< XResultSet > xResultSet = pResultSet; 1705 pResultSet->setRows( aResults ); 1706 1707 return xResultSet; 1708 } 1709 1710 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getBestRowIdentifier( 1711 const Any&, const OUString&, const OUString&, sal_Int32, 1712 sal_Bool ) 1713 { 1714 OSL_FAIL("Not implemented yet!"); 1715 // TODO implement 1716 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eBestRowIdentifier); 1717 } 1718 1719 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTablePrivileges( 1720 const Any& /*aCatalog*/, 1721 const OUString& /*sSchemaPattern*/, 1722 const OUString& sTableNamePattern) 1723 { 1724 SAL_INFO("connectivity.firebird", "getTablePrivileges() with " 1725 "TableNamePattern: " << sTableNamePattern); 1726 1727 ODatabaseMetaDataResultSet* pResultSet = new 1728 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTablePrivileges); 1729 uno::Reference< XResultSet > xResultSet = pResultSet; 1730 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1731 1732 // TODO: column specific privileges are included, we may need 1733 // to have WHERE RDB$FIELD_NAME = NULL or similar. 1734 static const char wld[] = "%"; 1735 OUStringBuffer queryBuf( 1736 "SELECT " 1737 "priv.RDB$RELATION_NAME, " // 1 1738 "priv.RDB$GRANTOR," // 2 1739 "priv.RDB$USER, " // 3 Grantee 1740 "priv.RDB$PRIVILEGE, " // 4 1741 "priv.RDB$GRANT_OPTION " // 5 is Grantable 1742 "FROM RDB$USER_PRIVILEGES priv "); 1743 1744 if (!sTableNamePattern.isEmpty()) 1745 { 1746 OUString sAppend; 1747 if (sTableNamePattern.match(wld)) 1748 sAppend = "WHERE priv.RDB$RELATION_NAME LIKE '%' "; 1749 else 1750 sAppend = "WHERE priv.RDB$RELATION_NAME = '%' "; 1751 1752 queryBuf.append(sAppend.replaceAll(wld, sTableNamePattern)); 1753 } 1754 queryBuf.append(" ORDER BY priv.RDB$RELATION_TYPE, " 1755 "priv.RDB$RELATION_NAME, " 1756 "priv.RDB$PRIVILEGE"); 1757 1758 OUString query = queryBuf.makeStringAndClear(); 1759 1760 uno::Reference< XResultSet > rs = statement->executeQuery(query.getStr()); 1761 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1762 ODatabaseMetaDataResultSet::ORows aResults; 1763 1764 ODatabaseMetaDataResultSet::ORow aRow(8); 1765 aRow[0] = new ORowSetValueDecorator(); // Unused 1766 aRow[1] = new ORowSetValueDecorator(); // TABLE_CAT unsupported 1767 aRow[2] = new ORowSetValueDecorator(); // TABLE_SCHEM unsupported. 1768 1769 while( rs->next() ) 1770 { 1771 // 3. TABLE_NAME 1772 aRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1773 aRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); // 4. GRANTOR 1774 aRow[5] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(3))); // 5. GRANTEE 1775 aRow[6] = new ORowSetValueDecorator(xRow->getString(4)); // 6. Privilege 1776 aRow[7] = new ORowSetValueDecorator(bool(xRow->getBoolean(5))); // 7. Is Grantable 1777 1778 aResults.push_back(aRow); 1779 } 1780 1781 pResultSet->setRows( aResults ); 1782 1783 return xResultSet; 1784 } 1785 1786 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCrossReference( 1787 const Any&, const OUString&, 1788 const OUString&, const Any&, 1789 const OUString&, const OUString& ) 1790 { 1791 OSL_FAIL("Not implemented yet!"); 1792 // TODO implement 1793 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCrossReference); 1794 } 1795 1796 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getUDTs( const Any&, const OUString&, const OUString&, const Sequence< sal_Int32 >& ) 1797 { 1798 OSL_FAIL("Not implemented yet!"); 1799 // TODO implement 1800 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eUDTs); 1801 } 1802 1803 1804 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1805
