1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ 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/ColumnSearch.hpp> 29 #include <com/sun/star/sdbc/ColumnValue.hpp> 30 #include <com/sun/star/sdbc/DataType.hpp> 31 #include <com/sun/star/sdbc/IndexType.hpp> 32 #include <com/sun/star/sdbc/ResultSetType.hpp> 33 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 34 #include <com/sun/star/sdbc/SQLException.hpp> 35 #include <com/sun/star/sdbc/TransactionIsolation.hpp> 36 #include <com/sun/star/sdbc/XRow.hpp> 37 #include <com/sun/star/sdbc/KeyRule.hpp> 38 #include <com/sun/star/sdbc/Deferrability.hpp> 39 40 using namespace connectivity::firebird; 41 using namespace com::sun::star; 42 using namespace com::sun::star::uno; 43 using namespace com::sun::star::lang; 44 using namespace com::sun::star::beans; 45 using namespace com::sun::star::sdbc; 46 47 ODatabaseMetaData::ODatabaseMetaData(Connection* _pCon) 48 : m_pConnection(_pCon) 49 { 50 SAL_WARN_IF(!m_pConnection.is(), "connectivity.firebird", 51 "ODatabaseMetaData::ODatabaseMetaData: No connection set!"); 52 } 53 54 ODatabaseMetaData::~ODatabaseMetaData() 55 { 56 } 57 58 //----- Catalog Info -- UNSUPPORTED ------------------------------------------- 59 OUString SAL_CALL ODatabaseMetaData::getCatalogSeparator() 60 { 61 return OUString(); 62 } 63 64 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCatalogNameLength() 65 { 66 return -1; 67 } 68 69 OUString SAL_CALL ODatabaseMetaData::getCatalogTerm() 70 { 71 return OUString(); 72 } 73 74 sal_Bool SAL_CALL ODatabaseMetaData::isCatalogAtStart() 75 { 76 return false; 77 } 78 79 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInTableDefinitions() 80 { 81 return false; 82 } 83 84 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInIndexDefinitions() 85 { 86 return false; 87 } 88 89 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInDataManipulation( ) 90 { 91 return false; 92 } 93 94 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCatalogs() 95 { 96 OSL_FAIL("Not implemented yet!"); 97 // TODO implement 98 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCatalogs); 99 } 100 101 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInProcedureCalls() 102 { 103 return false; 104 } 105 106 sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions() 107 { 108 return false; 109 } 110 111 //----- Schema Info -- UNSUPPORTED -------------------------------------------- 112 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInProcedureCalls() 113 { 114 return false; 115 } 116 117 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions() 118 { 119 return false; 120 } 121 122 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInDataManipulation() 123 { 124 return false; 125 } 126 127 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInIndexDefinitions() 128 { 129 return false; 130 } 131 132 sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInTableDefinitions() 133 { 134 return false; 135 } 136 137 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxSchemaNameLength() 138 { 139 return -1; 140 } 141 142 OUString SAL_CALL ODatabaseMetaData::getSchemaTerm() 143 { 144 return OUString(); 145 } 146 147 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getSchemas() 148 { 149 OSL_FAIL("Not implemented yet!"); 150 // TODO implement 151 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eSchemas); 152 } 153 154 //----- Max Sizes/Lengths ----------------------------------------------------- 155 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxBinaryLiteralLength() 156 { 157 return 32767; 158 } 159 160 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxRowSize() 161 { 162 return 32767; 163 } 164 165 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCharLiteralLength() 166 { 167 return 32767; 168 } 169 170 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnNameLength() 171 { 172 return 31; 173 } 174 175 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInIndex() 176 { 177 // TODO: No idea. 178 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/ 179 return 16; 180 } 181 182 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCursorNameLength() 183 { 184 return 32; 185 } 186 187 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxConnections() 188 { 189 return 100; // Arbitrary 190 } 191 192 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInTable() 193 { 194 // May however be smaller. 195 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/ 196 return 32767; 197 } 198 199 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatementLength() 200 { 201 return 32767; 202 } 203 204 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTableNameLength() 205 { 206 return 31; 207 } 208 209 sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTablesInSelect( ) 210 { 211 return 0; // 0 means no limit 212 } 213 214 215 sal_Bool SAL_CALL ODatabaseMetaData::doesMaxRowSizeIncludeBlobs( ) 216 { 217 return false; 218 } 219 220 // ---- Identifiers ----------------------------------------------------------- 221 // Only quoted identifiers are case sensitive, unquoted are case insensitive 222 OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() 223 { 224 return "\""; 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 true; 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 (void)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 m_pConnection; 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 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 785 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTableTypes); 786 787 ODatabaseMetaDataResultSet::ORows aResults; 788 ODatabaseMetaDataResultSet::ORow aRow(2); 789 790 aRow[0] = new ORowSetValueDecorator(); // unused 791 792 // TODO Put these statics to one place 793 // like postgreSQL's Statics class. 794 795 aRow[1] = new ORowSetValueDecorator(OUString("TABLE")); 796 aResults.push_back(aRow); 797 798 aRow[1] = new ORowSetValueDecorator(OUString("VIEW")); 799 aResults.push_back(aRow); 800 801 aRow[1] = new ORowSetValueDecorator(OUString("SYSTEM TABLE")); 802 aResults.push_back(aRow); 803 804 pResultSet->setRows(std::move(aResults)); 805 return pResultSet; 806 } 807 808 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTypeInfo() 809 { 810 SAL_INFO("connectivity.firebird", "getTypeInfo()"); 811 812 // this returns an empty resultset where the column-names are already set 813 // in special the metadata of the resultset already returns the right columns 814 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = 815 new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTypeInfo); 816 static ODatabaseMetaDataResultSet::ORows aResults = []() 817 { 818 ODatabaseMetaDataResultSet::ORows tmp; 819 ODatabaseMetaDataResultSet::ORow aRow(19); 820 821 // Common data 822 aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue(); // Literal quote marks 823 aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue(); // Literal quote marks 824 aRow[7] = new ORowSetValueDecorator(true); // Nullable 825 aRow[8] = new ORowSetValueDecorator(true); // Case sensitive 826 aRow[10] = new ORowSetValueDecorator(false); // Is unsigned 827 // FIXED_PREC_SCALE: docs state "can it be a money value? " however 828 // in reality this causes Base to treat all numbers as money formatted 829 // by default which is wrong (and formatting as money value is still 830 // possible for all values). 831 aRow[11] = new ORowSetValueDecorator(false); 832 // Localised Type Name -- TODO: implement (but can be null): 833 aRow[13] = new ORowSetValueDecorator(); 834 aRow[16] = new ORowSetValueDecorator(); // Unused 835 aRow[17] = new ORowSetValueDecorator(); // Unused 836 aRow[18] = new ORowSetValueDecorator(sal_Int16(10));// Radix 837 838 // Char 839 aRow[1] = new ORowSetValueDecorator(OUString("CHAR")); 840 aRow[2] = new ORowSetValueDecorator(DataType::CHAR); 841 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 842 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 843 aRow[9] = new ORowSetValueDecorator( 844 sal_Int16(ColumnSearch::FULL)); // Searchable 845 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 846 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 847 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 848 tmp.push_back(aRow); 849 850 // Varchar 851 aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); 852 aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR); 853 aRow[3] = new ORowSetValueDecorator(sal_Int16(32765)); // Prevision = max length 854 aRow[6] = new ORowSetValueDecorator(OUString("length")); // Create Params 855 aRow[9] = new ORowSetValueDecorator( 856 sal_Int16(ColumnSearch::FULL)); // Searchable 857 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 858 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 859 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 860 tmp.push_back(aRow); 861 862 // Binary (CHAR); we use the Firebird synonym CHARACTER 863 // to fool LO into seeing it as different types. 864 // It is distinguished from Text type by its character set OCTETS; 865 // that will be added by Tables::createStandardColumnPart 866 aRow[1] = new ORowSetValueDecorator(OUString("CHARACTER")); 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); see comment above about BINARY 877 aRow[1] = new ORowSetValueDecorator(OUString("CHARACTER VARYING")); 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 SUB_TYPE TEXT")); // 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[1] = new ORowSetValueDecorator(OUString("BLOB SUB_TYPE " + OUString::number(static_cast<short>(BlobSubtype::Image))) ); // BLOB, with subtype 0 899 aRow[2] = new ORowSetValueDecorator(DataType::LONGVARBINARY); 900 tmp.push_back(aRow); 901 902 // Integer Types common 903 { 904 aRow[6] = new ORowSetValueDecorator(); // Create Params 905 aRow[9] = new ORowSetValueDecorator( 906 sal_Int16(ColumnSearch::FULL)); // Searchable 907 aRow[12] = new ORowSetValueDecorator(true); // Autoincrement 908 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 909 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 910 } 911 // Smallint (SQL_SHORT) 912 aRow[1] = new ORowSetValueDecorator(OUString("SMALLINT")); 913 aRow[2] = new ORowSetValueDecorator(DataType::SMALLINT); 914 aRow[3] = new ORowSetValueDecorator(sal_Int16(5)); // Prevision 915 tmp.push_back(aRow); 916 // Integer (SQL_LONG) 917 aRow[1] = new ORowSetValueDecorator(OUString("INTEGER")); 918 aRow[2] = new ORowSetValueDecorator(DataType::INTEGER); 919 aRow[3] = new ORowSetValueDecorator(sal_Int16(10)); // Precision 920 tmp.push_back(aRow); 921 // Bigint (SQL_INT64) 922 aRow[1] = new ORowSetValueDecorator(OUString("BIGINT")); 923 aRow[2] = new ORowSetValueDecorator(DataType::BIGINT); 924 aRow[3] = new ORowSetValueDecorator(sal_Int16(20)); // Precision 925 tmp.push_back(aRow); 926 927 // Decimal Types common 928 { 929 aRow[9] = new ORowSetValueDecorator( 930 sal_Int16(ColumnSearch::FULL)); // Searchable 931 aRow[12] = new ORowSetValueDecorator(true); // Autoincrement 932 } 933 934 aRow[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params 935 // Numeric 936 aRow[1] = new ORowSetValueDecorator(OUString("NUMERIC")); 937 aRow[2] = new ORowSetValueDecorator(DataType::NUMERIC); 938 aRow[3] = new ORowSetValueDecorator(sal_Int16(18)); // Precision 939 aRow[14] = new ORowSetValueDecorator(sal_Int16(0)); // Minimum scale 940 aRow[15] = new ORowSetValueDecorator(sal_Int16(18)); // Max scale 941 tmp.push_back(aRow); 942 // Decimal 943 aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL")); 944 aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); 945 aRow[3] = new ORowSetValueDecorator(sal_Int16(18)); // Precision 946 aRow[14] = new ORowSetValueDecorator(sal_Int16(0)); // Minimum scale 947 aRow[15] = new ORowSetValueDecorator(sal_Int16(18)); // Max scale 948 tmp.push_back(aRow); 949 950 aRow[6] = new ORowSetValueDecorator(); // Create Params 951 // Float (SQL_FLOAT) 952 aRow[1] = new ORowSetValueDecorator(OUString("FLOAT")); 953 aRow[2] = new ORowSetValueDecorator(DataType::FLOAT); 954 aRow[3] = new ORowSetValueDecorator(sal_Int16(7)); // Precision 955 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 956 aRow[15] = new ORowSetValueDecorator(sal_Int16(7)); // Max scale 957 tmp.push_back(aRow); 958 // Double (SQL_DOUBLE) 959 aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE PRECISION")); 960 aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE); 961 aRow[3] = new ORowSetValueDecorator(sal_Int16(15)); // Precision 962 aRow[14] = new ORowSetValueDecorator(sal_Int16(1)); // Minimum scale 963 aRow[15] = new ORowSetValueDecorator(sal_Int16(15)); // Max scale 964 tmp.push_back(aRow); 965 966 // TODO: no idea whether D_FLOAT corresponds to an sql type 967 968 // SQL_TIMESTAMP 969 aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP")); 970 aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP); 971 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 972 aRow[6] = new ORowSetValueDecorator(); // Create Params 973 aRow[9] = new ORowSetValueDecorator( 974 sal_Int16(ColumnSearch::FULL)); // Searchable 975 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 976 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 977 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 978 tmp.push_back(aRow); 979 980 // SQL_TYPE_TIME 981 aRow[1] = new ORowSetValueDecorator(OUString("TIME")); 982 aRow[2] = new ORowSetValueDecorator(DataType::TIME); 983 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 984 aRow[6] = new ORowSetValueDecorator(); // Create Params 985 aRow[9] = new ORowSetValueDecorator( 986 sal_Int16(ColumnSearch::FULL)); // Searchable 987 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 988 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 989 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 990 tmp.push_back(aRow); 991 992 // SQL_TYPE_DATE 993 aRow[1] = new ORowSetValueDecorator(OUString("DATE")); 994 aRow[2] = new ORowSetValueDecorator(DataType::DATE); 995 aRow[3] = new ORowSetValueDecorator(sal_Int32(8)); // Prevision = max length 996 aRow[6] = new ORowSetValueDecorator(); // Create Params 997 aRow[9] = new ORowSetValueDecorator( 998 sal_Int16(ColumnSearch::FULL)); // Searchable 999 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 1000 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1001 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1002 tmp.push_back(aRow); 1003 1004 // SQL_BLOB 1005 aRow[1] = new ORowSetValueDecorator(OUString("BLOB SUB_TYPE BINARY")); 1006 aRow[2] = new ORowSetValueDecorator(DataType::BLOB); 1007 aRow[3] = new ORowSetValueDecorator(sal_Int32(0)); // Prevision = max length 1008 aRow[6] = new ORowSetValueDecorator(); // Create Params 1009 aRow[9] = new ORowSetValueDecorator( 1010 sal_Int16(ColumnSearch::NONE)); // Searchable 1011 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 1012 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1013 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1014 tmp.push_back(aRow); 1015 1016 // SQL_BOOLEAN 1017 aRow[1] = new ORowSetValueDecorator(OUString("BOOLEAN")); 1018 aRow[2] = new ORowSetValueDecorator(DataType::BOOLEAN); 1019 aRow[3] = new ORowSetValueDecorator(sal_Int32(1)); // Prevision = max length 1020 aRow[6] = new ORowSetValueDecorator(); // Create Params 1021 aRow[9] = new ORowSetValueDecorator( 1022 sal_Int16(ColumnSearch::BASIC)); // Searchable 1023 aRow[12] = new ORowSetValueDecorator(false); // Autoincrement 1024 aRow[14] = ODatabaseMetaDataResultSet::get0Value(); // Minimum scale 1025 aRow[15] = ODatabaseMetaDataResultSet::get0Value(); // Max scale 1026 tmp.push_back(aRow); 1027 return tmp; 1028 }(); 1029 pResultSet->setRows(ODatabaseMetaDataResultSet::ORows(aResults)); 1030 return pResultSet; 1031 } 1032 1033 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumnPrivileges( 1034 const Any& /*aCatalog*/, 1035 const OUString& /*sSchema*/, 1036 const OUString& sTable, 1037 const OUString& sColumnNamePattern) 1038 { 1039 SAL_INFO("connectivity.firebird", "getColumnPrivileges() with " 1040 "Table: " << sTable 1041 << " & ColumnNamePattern: " << sColumnNamePattern); 1042 1043 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1044 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumnPrivileges); 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); 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( std::move(aResults) ); 1103 1104 return pResultSet; 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); 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 sCharsetName); 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 > xBlob = xRow->getBlob(3); 1247 if (xBlob.is()) 1248 { 1249 const sal_Int64 aBlobLength = xBlob->length(); 1250 if (aBlobLength > SAL_MAX_INT32) 1251 { 1252 SAL_WARN("connectivity.firebird", "getBytes can't return " << aBlobLength << " bytes but only max " << SAL_MAX_INT32); 1253 aDescription = OUString(reinterpret_cast<char*>(xBlob->getBytes(1, SAL_MAX_INT32).getArray()), 1254 SAL_MAX_INT32, 1255 RTL_TEXTENCODING_UTF8); 1256 } 1257 else 1258 { 1259 aDescription = OUString(reinterpret_cast<char*>(xBlob->getBytes(1, static_cast<sal_Int32>(aBlobLength)).getArray()), 1260 aBlobLength, 1261 RTL_TEXTENCODING_UTF8); 1262 } 1263 } 1264 aCurrentRow[12] = new ORowSetValueDecorator(aDescription); 1265 } 1266 // 13. Default -- may be omitted. 1267 { 1268 uno::Reference< XBlob > xDefaultValueBlob = xRow->getBlob(4); 1269 if (xDefaultValueBlob.is()) 1270 { 1271 // TODO: Implement 1272 } 1273 aCurrentRow[13] = new ORowSetValueDecorator(); 1274 } 1275 1276 // 16. Bytes in Column for char 1277 if (aType == SQL_TEXT) 1278 { 1279 aCurrentRow[16] = new ORowSetValueDecorator(xRow->getShort(8)); 1280 } 1281 else if (aType == SQL_VARYING) 1282 { 1283 aCurrentRow[16] = new ORowSetValueDecorator(sal_Int32(32767)); 1284 } 1285 else 1286 { 1287 aCurrentRow[16] = new ORowSetValueDecorator(sal_Int32(0)); 1288 } 1289 // 17. Index of column 1290 { 1291 short nColumnNumber = xRow->getShort(5); 1292 // Firebird stores column numbers beginning with 0 internally 1293 // SDBC expects column numbering to begin with 1. 1294 aCurrentRow[17] = new ORowSetValueDecorator(sal_Int32(nColumnNumber + 1)); 1295 } 1296 // 18. Is nullable 1297 if (xRow->getShort(9)) 1298 { 1299 aCurrentRow[18] = new ORowSetValueDecorator(OUString("NO")); 1300 } 1301 else 1302 { 1303 aCurrentRow[18] = new ORowSetValueDecorator(OUString("YES")); 1304 } 1305 1306 aResults.push_back(aCurrentRow); 1307 } 1308 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1309 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumns); 1310 pResultSet->setRows( std::move(aResults) ); 1311 1312 return pResultSet; 1313 } 1314 1315 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTables( 1316 const Any& /*catalog*/, 1317 const OUString& /*schemaPattern*/, 1318 const OUString& tableNamePattern, 1319 const Sequence< OUString >& types) 1320 { 1321 SAL_INFO("connectivity.firebird", "getTables() with " 1322 "TableNamePattern: " << tableNamePattern); 1323 1324 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1325 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables); 1326 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1327 1328 static const char wld[] = "%"; 1329 OUStringBuffer queryBuf( 1330 "SELECT " 1331 "RDB$RELATION_NAME, " 1332 "RDB$SYSTEM_FLAG, " 1333 "RDB$RELATION_TYPE, " 1334 "RDB$DESCRIPTION, " 1335 "RDB$VIEW_BLR " 1336 "FROM RDB$RELATIONS " 1337 "WHERE "); 1338 1339 // TODO: GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM 1340 if (!types.hasElements() || (types.getLength() == 1 && types[0].match(wld))) 1341 { 1342 // All table types? I.e. includes system tables. 1343 queryBuf.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1) "); 1344 } 1345 else 1346 { 1347 queryBuf.append("( (0 = 1) "); 1348 for (OUString const & t : types) 1349 { 1350 if (t == "SYSTEM TABLE") 1351 queryBuf.append("OR (RDB$SYSTEM_FLAG = 1 AND RDB$VIEW_BLR IS NULL) "); 1352 else if (t == "TABLE") 1353 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NULL) "); 1354 else if (t == "VIEW") 1355 queryBuf.append("OR (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0 AND RDB$VIEW_BLR IS NOT NULL) "); 1356 else 1357 throw SQLException(); // TODO: implement other types, see above. 1358 } 1359 queryBuf.append(") "); 1360 } 1361 1362 if (!tableNamePattern.isEmpty()) 1363 { 1364 OUString sAppend; 1365 if (tableNamePattern.match(wld)) 1366 sAppend = "AND RDB$RELATION_NAME LIKE '%' "; 1367 else 1368 sAppend = "AND RDB$RELATION_NAME = '%' "; 1369 1370 queryBuf.append(sAppend.replaceAll(wld, tableNamePattern)); 1371 } 1372 1373 queryBuf.append(" ORDER BY RDB$RELATION_TYPE, RDB$RELATION_NAME"); 1374 1375 OUString query = queryBuf.makeStringAndClear(); 1376 1377 uno::Reference< XResultSet > rs = statement->executeQuery(query); 1378 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1379 ODatabaseMetaDataResultSet::ORows aResults; 1380 1381 ODatabaseMetaDataResultSet::ORow aCurrentRow(6); 1382 aCurrentRow[0] = new ORowSetValueDecorator(); // 0. Unused 1383 aCurrentRow[1] = new ORowSetValueDecorator(); // 1. Table_Cat Unsupported 1384 aCurrentRow[2] = new ORowSetValueDecorator(); // 2. Table_Schem Unsupported 1385 1386 while( rs->next() ) 1387 { 1388 // 3. TABLE_NAME 1389 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1390 // 4. TABLE_TYPE 1391 { 1392 // TODO: check this as the docs are a bit unclear. 1393 sal_Int16 nSystemFlag = xRow->getShort(2); 1394 sal_Int16 nTableType = xRow->getShort(3); 1395 xRow->getBlob(5); // We have to retrieve a column to verify it is null. 1396 bool aIsView = !xRow->wasNull(); 1397 OUString sTableType; 1398 1399 if (nSystemFlag == 1) 1400 { 1401 sTableType = "SYSTEM TABLE"; 1402 } 1403 else if (aIsView) 1404 { 1405 sTableType = "VIEW"; 1406 } 1407 else 1408 { 1409 if (nTableType == 0) 1410 sTableType = "TABLE"; 1411 } 1412 1413 aCurrentRow[4] = new ORowSetValueDecorator(sTableType); 1414 } 1415 // 5. REMARKS 1416 { 1417 uno::Reference< XClob > xClob = xRow->getClob(4); 1418 if (xClob.is()) 1419 { 1420 aCurrentRow[5] = new ORowSetValueDecorator(xClob->getSubString(1, xClob->length())); 1421 } 1422 } 1423 1424 aResults.push_back(aCurrentRow); 1425 } 1426 1427 pResultSet->setRows( std::move(aResults) ); 1428 1429 return pResultSet; 1430 } 1431 1432 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedureColumns( 1433 const Any&, const OUString&, 1434 const OUString&, const OUString& ) 1435 { 1436 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1437 OSL_FAIL("Not implemented yet!"); 1438 // TODO implement 1439 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedureColumns); 1440 } 1441 1442 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getProcedures( 1443 const Any&, const OUString&, 1444 const OUString& ) 1445 { 1446 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1447 OSL_FAIL("Not implemented yet!"); 1448 // TODO implement 1449 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedures); 1450 } 1451 1452 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getVersionColumns( 1453 const Any&, const OUString&, const OUString& ) 1454 { 1455 SAL_WARN("connectivity.firebird", "Not yet implemented"); 1456 OSL_FAIL("Not implemented yet!"); 1457 // TODO implement 1458 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eVersionColumns); 1459 } 1460 1461 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getExportedKeys( 1462 const Any&, const OUString&, const OUString& table ) 1463 { 1464 return ODatabaseMetaData::lcl_getKeys(false, table); 1465 } 1466 1467 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getImportedKeys( 1468 const Any&, const OUString&, const OUString& table ) 1469 { 1470 return ODatabaseMetaData::lcl_getKeys(true, table); 1471 } 1472 1473 uno::Reference< XResultSet > ODatabaseMetaData::lcl_getKeys(const bool bIsImport, std::u16string_view table ) 1474 { 1475 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1476 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eImportedKeys); 1477 1478 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1479 1480 OUString sSQL = "SELECT " 1481 "RDB$REF_CONSTRAINTS.RDB$UPDATE_RULE, " // 1 update rule 1482 "RDB$REF_CONSTRAINTS.RDB$DELETE_RULE, " // 2 delete rule 1483 "RDB$REF_CONSTRAINTS.RDB$CONST_NAME_UQ, " // 3 primary or unique key name 1484 "RDB$REF_CONSTRAINTS.RDB$CONSTRAINT_NAME, " // 4 foreign key name 1485 "PRIM.RDB$DEFERRABLE, " // 5 deferrability 1486 "PRIM.RDB$INITIALLY_DEFERRED, " // 6 deferrability 1487 "PRIM.RDB$RELATION_NAME, " // 7 PK table name 1488 "PRIMARY_INDEX.RDB$FIELD_NAME, " // 8 PK column name 1489 "PRIMARY_INDEX.RDB$FIELD_POSITION, " // 9 PK sequence number 1490 "FOREI.RDB$RELATION_NAME, " // 10 FK table name 1491 "FOREIGN_INDEX.RDB$FIELD_NAME " // 11 FK column name 1492 "FROM RDB$REF_CONSTRAINTS " 1493 "INNER JOIN RDB$RELATION_CONSTRAINTS AS PRIM " 1494 "ON RDB$REF_CONSTRAINTS.RDB$CONST_NAME_UQ = PRIM.RDB$CONSTRAINT_NAME " 1495 "INNER JOIN RDB$RELATION_CONSTRAINTS AS FOREI " 1496 "ON RDB$REF_CONSTRAINTS.RDB$CONSTRAINT_NAME = FOREI.RDB$CONSTRAINT_NAME " 1497 "INNER JOIN RDB$INDEX_SEGMENTS AS PRIMARY_INDEX " 1498 "ON PRIM.RDB$INDEX_NAME = PRIMARY_INDEX.RDB$INDEX_NAME " 1499 "INNER JOIN RDB$INDEX_SEGMENTS AS FOREIGN_INDEX " 1500 "ON FOREI.RDB$INDEX_NAME = FOREIGN_INDEX.RDB$INDEX_NAME " 1501 "WHERE FOREI.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY' "; 1502 if (bIsImport) 1503 sSQL += OUString::Concat("AND FOREI.RDB$RELATION_NAME = '")+ table +"'"; 1504 else 1505 sSQL += OUString::Concat("AND PRIM.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( std::move(aResults) ); 1556 return pResultSet; 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 OUString sAppend = "WHERE constr.RDB$RELATION_NAME = '%' "; 1568 OUString sQuery = "SELECT " 1569 "constr.RDB$RELATION_NAME, " // 1. Table Name 1570 "inds.RDB$FIELD_NAME, " // 2. Column Name 1571 "inds.RDB$FIELD_POSITION, " // 3. Sequence Number 1572 "constr.RDB$CONSTRAINT_NAME " // 4 Constraint name 1573 "FROM RDB$RELATION_CONSTRAINTS constr " 1574 "JOIN RDB$INDEX_SEGMENTS inds " 1575 "on (constr.RDB$INDEX_NAME = inds.RDB$INDEX_NAME) " + 1576 sAppend.replaceAll("%", sTable) + 1577 "AND constr.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " 1578 "ORDER BY inds.RDB$FIELD_NAME"; 1579 1580 uno::Reference< XStatement > xStatement = m_pConnection->createStatement(); 1581 uno::Reference< XResultSet > xRs = xStatement->executeQuery(sQuery); 1582 uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW ); 1583 1584 ODatabaseMetaDataResultSet::ORows aResults; 1585 ODatabaseMetaDataResultSet::ORow aCurrentRow(7); 1586 1587 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0 1588 aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null 1589 aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null 1590 1591 while(xRs->next()) 1592 { 1593 // 3. Table Name 1594 if (xRs->getRow() == 1) // Table name doesn't change, so only retrieve once 1595 { 1596 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1597 } 1598 // 4. Column Name 1599 aCurrentRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); 1600 // 5. KEY_SEQ (which key in the sequence) 1601 aCurrentRow[5] = new ORowSetValueDecorator(xRow->getShort(3)); 1602 // 6. Primary Key Name 1603 aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4))); 1604 1605 aResults.push_back(aCurrentRow); 1606 } 1607 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1608 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys); 1609 pResultSet->setRows( std::move(aResults) ); 1610 1611 return pResultSet; 1612 } 1613 1614 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getIndexInfo( 1615 const Any& /*aCatalog*/, 1616 const OUString& /*sSchema*/, 1617 const OUString& sTable, 1618 sal_Bool bIsUnique, 1619 sal_Bool) // TODO: what is bIsApproximate? 1620 1621 { 1622 // Apparently this method can also return a "tableIndexStatistic" 1623 // However this is only mentioned in XDatabaseMetaData.idl (whose comments 1624 // are duplicated in the postgresql driver), and is otherwise undocumented. 1625 SAL_INFO("connectivity.firebird", "getPrimaryKeys() with " 1626 "Table: " << sTable); 1627 1628 OUStringBuffer aQueryBuf("SELECT " 1629 "indices.RDB$RELATION_NAME, " // 1. Table Name 1630 "index_segments.RDB$FIELD_NAME, " // 2. Column Name 1631 "index_segments.RDB$FIELD_POSITION, " // 3. Sequence Number 1632 "indices.RDB$INDEX_NAME, " // 4. Index name 1633 "indices.RDB$UNIQUE_FLAG, " // 5. Unique Flag 1634 "indices.RDB$INDEX_TYPE " // 6. Index Type 1635 "FROM RDB$INDICES indices " 1636 "JOIN RDB$INDEX_SEGMENTS index_segments " 1637 "on (indices.RDB$INDEX_NAME = index_segments.RDB$INDEX_NAME) " 1638 "WHERE indices.RDB$RELATION_NAME = '" + sTable + "' " 1639 "AND (indices.RDB$SYSTEM_FLAG = 0) "); 1640 // Not sure whether we should exclude system indices, but otoh. we never 1641 // actually deal with system tables (system indices only apply to system 1642 // tables) within the GUI. 1643 1644 // Only filter if true (according to the docs), i.e.: 1645 // If false we return all indices, if true we return only unique indices 1646 if (bIsUnique) 1647 aQueryBuf.append("AND (indices.RDB$UNIQUE_FLAG = 1) "); 1648 1649 OUString sQuery = aQueryBuf.makeStringAndClear(); 1650 1651 uno::Reference< XStatement > xStatement = m_pConnection->createStatement(); 1652 uno::Reference< XResultSet > xRs = xStatement->executeQuery(sQuery); 1653 uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW ); 1654 1655 ODatabaseMetaDataResultSet::ORows aResults; 1656 ODatabaseMetaDataResultSet::ORow aCurrentRow(14); 1657 1658 aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0 1659 aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null 1660 aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null 1661 aCurrentRow[5] = new ORowSetValueDecorator(); // Index Catalog -- can be null 1662 // Wikipedia indicates: 1663 // 'Firebird makes all indices of the database behave like well-tuned "clustered indexes" used by other architectures.' 1664 // but it's not "CLUSTERED", neither "STATISTIC" nor "HASHED" (the other specific types from offapi/com/sun/star/sdbc/IndexType.idl) 1665 // According to https://www.ibphoenix.com/resources/documents/design/doc_18, 1666 // it seems another type => OTHER 1667 aCurrentRow[7] = new ORowSetValueDecorator(IndexType::OTHER); // 7. INDEX TYPE 1668 aCurrentRow[13] = new ORowSetValueDecorator(); // Filter Condition -- can be null 1669 1670 while(xRs->next()) 1671 { 1672 // 3. Table Name 1673 if (xRs->getRow() == 1) // Table name doesn't change, so only retrieve once 1674 { 1675 aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1676 } 1677 1678 // 4. NON_UNIQUE -- i.e. specifically negate here. 1679 aCurrentRow[4] = new ORowSetValueDecorator(xRow->getShort(5) == 0); 1680 // 6. INDEX NAME 1681 aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4))); 1682 1683 // 8. ORDINAL POSITION 1684 aCurrentRow[8] = new ORowSetValueDecorator(xRow->getShort(3)); 1685 // 9. COLUMN NAME 1686 aCurrentRow[9] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); 1687 // 10. ASC(ending)/DESC(ending) 1688 if (xRow->getShort(6) == 1) 1689 aCurrentRow[10] = new ORowSetValueDecorator(OUString("D")); 1690 else 1691 aCurrentRow[10] = new ORowSetValueDecorator(OUString("A")); 1692 // TODO: double check this^^^, doesn't seem to be officially documented anywhere. 1693 // 11. CARDINALITY 1694 aCurrentRow[11] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this 1695 // 12. PAGES 1696 aCurrentRow[12] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this 1697 1698 aResults.push_back(aCurrentRow); 1699 } 1700 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1701 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys); 1702 pResultSet->setRows( std::move(aResults) ); 1703 1704 return pResultSet; 1705 } 1706 1707 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getBestRowIdentifier( 1708 const Any&, const OUString&, const OUString&, sal_Int32, 1709 sal_Bool ) 1710 { 1711 OSL_FAIL("Not implemented yet!"); 1712 // TODO implement 1713 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eBestRowIdentifier); 1714 } 1715 1716 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTablePrivileges( 1717 const Any& /*aCatalog*/, 1718 const OUString& /*sSchemaPattern*/, 1719 const OUString& sTableNamePattern) 1720 { 1721 SAL_INFO("connectivity.firebird", "getTablePrivileges() with " 1722 "TableNamePattern: " << sTableNamePattern); 1723 1724 rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new 1725 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTablePrivileges); 1726 uno::Reference< XStatement > statement = m_pConnection->createStatement(); 1727 1728 // TODO: column specific privileges are included, we may need 1729 // to have WHERE RDB$FIELD_NAME = NULL or similar. 1730 static const char wld[] = "%"; 1731 OUStringBuffer queryBuf( 1732 "SELECT " 1733 "priv.RDB$RELATION_NAME, " // 1 1734 "priv.RDB$GRANTOR," // 2 1735 "priv.RDB$USER, " // 3 Grantee 1736 "priv.RDB$PRIVILEGE, " // 4 1737 "priv.RDB$GRANT_OPTION " // 5 is Grantable 1738 "FROM RDB$USER_PRIVILEGES priv "); 1739 1740 if (!sTableNamePattern.isEmpty()) 1741 { 1742 OUString sAppend; 1743 if (sTableNamePattern.match(wld)) 1744 sAppend = "WHERE priv.RDB$RELATION_NAME LIKE '%' "; 1745 else 1746 sAppend = "WHERE priv.RDB$RELATION_NAME = '%' "; 1747 1748 queryBuf.append(sAppend.replaceAll(wld, sTableNamePattern)); 1749 } 1750 queryBuf.append(" ORDER BY priv.RDB$RELATION_TYPE, " 1751 "priv.RDB$RELATION_NAME, " 1752 "priv.RDB$PRIVILEGE"); 1753 1754 OUString query = queryBuf.makeStringAndClear(); 1755 1756 uno::Reference< XResultSet > rs = statement->executeQuery(query); 1757 uno::Reference< XRow > xRow( rs, UNO_QUERY_THROW ); 1758 ODatabaseMetaDataResultSet::ORows aResults; 1759 1760 ODatabaseMetaDataResultSet::ORow aRow(8); 1761 aRow[0] = new ORowSetValueDecorator(); // Unused 1762 aRow[1] = new ORowSetValueDecorator(); // TABLE_CAT unsupported 1763 aRow[2] = new ORowSetValueDecorator(); // TABLE_SCHEM unsupported. 1764 1765 while( rs->next() ) 1766 { 1767 // 3. TABLE_NAME 1768 aRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1))); 1769 aRow[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2))); // 4. GRANTOR 1770 aRow[5] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(3))); // 5. GRANTEE 1771 aRow[6] = new ORowSetValueDecorator(xRow->getString(4)); // 6. Privilege 1772 aRow[7] = new ORowSetValueDecorator(bool(xRow->getBoolean(5))); // 7. Is Grantable 1773 1774 aResults.push_back(aRow); 1775 } 1776 1777 pResultSet->setRows( std::move(aResults) ); 1778 1779 return pResultSet; 1780 } 1781 1782 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getCrossReference( 1783 const Any&, const OUString&, 1784 const OUString&, const Any&, 1785 const OUString&, const OUString& ) 1786 { 1787 OSL_FAIL("Not implemented yet!"); 1788 // TODO implement 1789 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCrossReference); 1790 } 1791 1792 uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getUDTs( const Any&, const OUString&, const OUString&, const Sequence< sal_Int32 >& ) 1793 { 1794 OSL_FAIL("Not implemented yet!"); 1795 // TODO implement 1796 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eUDTs); 1797 } 1798 1799 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ 1800
