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