1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "DatabaseMetaData.hxx"
24 #include <rtl/ustrbuf.hxx>
25 #include <sal/log.hxx>
26 #include <FDatabaseMetaDataResultSet.hxx>
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>
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
;
47 ODatabaseMetaData::ODatabaseMetaData(Connection
* _pCon
)
48 : m_pConnection(_pCon
)
50 SAL_WARN_IF(!m_pConnection
.is(), "connectivity.firebird",
51 "ODatabaseMetaData::ODatabaseMetaData: No connection set!");
54 ODatabaseMetaData::~ODatabaseMetaData()
58 //----- Catalog Info -- UNSUPPORTED -------------------------------------------
59 OUString SAL_CALL
ODatabaseMetaData::getCatalogSeparator()
64 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxCatalogNameLength()
69 OUString SAL_CALL
ODatabaseMetaData::getCatalogTerm()
74 sal_Bool SAL_CALL
ODatabaseMetaData::isCatalogAtStart()
79 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCatalogsInTableDefinitions()
84 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCatalogsInIndexDefinitions()
89 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCatalogsInDataManipulation( )
94 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getCatalogs()
96 OSL_FAIL("Not implemented yet!");
98 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCatalogs
);
101 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCatalogsInProcedureCalls()
106 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions()
111 //----- Schema Info -- UNSUPPORTED --------------------------------------------
112 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSchemasInProcedureCalls()
117 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions()
122 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSchemasInDataManipulation()
127 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSchemasInIndexDefinitions()
132 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSchemasInTableDefinitions()
137 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxSchemaNameLength()
142 OUString SAL_CALL
ODatabaseMetaData::getSchemaTerm()
147 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getSchemas()
149 OSL_FAIL("Not implemented yet!");
151 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eSchemas
);
154 //----- Max Sizes/Lengths -----------------------------------------------------
155 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxBinaryLiteralLength()
160 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxRowSize()
165 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxCharLiteralLength()
170 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnNameLength()
175 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnsInIndex()
178 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/
182 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxCursorNameLength()
187 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxConnections()
189 return 100; // Arbitrary
192 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnsInTable()
194 // May however be smaller.
195 // See: http://www.firebirdsql.org/en/firebird-technical-specifications/
199 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxStatementLength()
204 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxTableNameLength()
209 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxTablesInSelect( )
211 return 0; // 0 means no limit
215 sal_Bool SAL_CALL
ODatabaseMetaData::doesMaxRowSizeIncludeBlobs( )
220 // ---- Identifiers -----------------------------------------------------------
221 // Only quoted identifiers are case sensitive, unquoted are case insensitive
222 OUString SAL_CALL
ODatabaseMetaData::getIdentifierQuoteString()
227 sal_Bool SAL_CALL
ODatabaseMetaData::supportsMixedCaseQuotedIdentifiers( )
232 sal_Bool SAL_CALL
ODatabaseMetaData::storesLowerCaseQuotedIdentifiers()
237 sal_Bool SAL_CALL
ODatabaseMetaData::storesMixedCaseQuotedIdentifiers()
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.
245 sal_Bool SAL_CALL
ODatabaseMetaData::storesUpperCaseQuotedIdentifiers()
250 // ---- Unquoted Identifiers -------------------------------------------------
251 // All unquoted identifiers are stored upper case.
252 sal_Bool SAL_CALL
ODatabaseMetaData::supportsMixedCaseIdentifiers()
257 sal_Bool SAL_CALL
ODatabaseMetaData::storesLowerCaseIdentifiers()
262 sal_Bool SAL_CALL
ODatabaseMetaData::storesMixedCaseIdentifiers()
267 sal_Bool SAL_CALL
ODatabaseMetaData::storesUpperCaseIdentifiers()
272 // ---- SQL Feature Support ---------------------------------------------------
273 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCoreSQLGrammar()
278 sal_Bool SAL_CALL
ODatabaseMetaData::supportsMinimumSQLGrammar()
283 sal_Bool SAL_CALL
ODatabaseMetaData::supportsAlterTableWithAddColumn()
288 sal_Bool SAL_CALL
ODatabaseMetaData::supportsAlterTableWithDropColumn()
293 sal_Bool SAL_CALL
ODatabaseMetaData::supportsPositionedDelete()
298 sal_Bool SAL_CALL
ODatabaseMetaData::supportsPositionedUpdate()
303 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOuterJoins()
308 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSelectForUpdate()
313 sal_Bool SAL_CALL
ODatabaseMetaData::allTablesAreSelectable()
315 // TODO: true if embedded, but unsure about remote server
319 sal_Bool SAL_CALL
ODatabaseMetaData::supportsConvert(sal_Int32
,
325 sal_Bool SAL_CALL
ODatabaseMetaData::supportsTypeConversion()
330 sal_Bool SAL_CALL
ODatabaseMetaData::supportsColumnAliasing()
335 sal_Bool SAL_CALL
ODatabaseMetaData::supportsTableCorrelationNames()
340 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxIndexLength( )
342 return 0; // 0 means no limit
345 sal_Bool SAL_CALL
ODatabaseMetaData::supportsNonNullableColumns( )
350 OUString SAL_CALL
ODatabaseMetaData::getExtraNameCharacters( )
355 sal_Bool SAL_CALL
ODatabaseMetaData::supportsDifferentTableCorrelationNames( )
359 // ---- Data definition stuff -------------------------------------------------
360 sal_Bool SAL_CALL
ODatabaseMetaData::dataDefinitionIgnoredInTransactions()
365 sal_Bool SAL_CALL
ODatabaseMetaData::dataDefinitionCausesTransactionCommit()
370 sal_Bool SAL_CALL
ODatabaseMetaData::supportsDataManipulationTransactionsOnly()
375 sal_Bool SAL_CALL
ODatabaseMetaData::
376 supportsDataDefinitionAndDataManipulationTransactions()
380 //----- Transaction Support --------------------------------------------------
381 sal_Bool SAL_CALL
ODatabaseMetaData::supportsTransactions()
386 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOpenStatementsAcrossRollback()
391 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOpenStatementsAcrossCommit()
396 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOpenCursorsAcrossCommit()
401 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOpenCursorsAcrossRollback()
406 sal_Bool SAL_CALL
ODatabaseMetaData::supportsMultipleTransactions()
411 sal_Bool SAL_CALL
ODatabaseMetaData::supportsTransactionIsolationLevel(
414 return aLevel
== TransactionIsolation::READ_UNCOMMITTED
415 || aLevel
== TransactionIsolation::READ_COMMITTED
416 || aLevel
== TransactionIsolation::REPEATABLE_READ
417 || aLevel
== TransactionIsolation::SERIALIZABLE
;
420 sal_Int32 SAL_CALL
ODatabaseMetaData::getDefaultTransactionIsolation()
422 return TransactionIsolation::REPEATABLE_READ
;
426 sal_Bool SAL_CALL
ODatabaseMetaData::supportsANSI92FullSQL( )
431 sal_Bool SAL_CALL
ODatabaseMetaData::supportsANSI92EntryLevelSQL( )
433 return true; // should be supported at least
436 sal_Bool SAL_CALL
ODatabaseMetaData::supportsIntegrityEnhancementFacility( )
441 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxStatements( )
443 return 0; // 0 means no limit
446 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxProcedureNameLength( )
448 return 31; // TODO: confirm
451 sal_Bool SAL_CALL
ODatabaseMetaData::allProceduresAreCallable( )
456 sal_Bool SAL_CALL
ODatabaseMetaData::supportsStoredProcedures( )
461 sal_Bool SAL_CALL
ODatabaseMetaData::isReadOnly( )
463 return m_pConnection
->isReadOnly();
466 sal_Bool SAL_CALL
ODatabaseMetaData::usesLocalFiles( )
468 return m_pConnection
->isEmbedded();
471 sal_Bool SAL_CALL
ODatabaseMetaData::usesLocalFilePerTable( )
476 sal_Bool SAL_CALL
ODatabaseMetaData::nullPlusNonNullIsNull( )
481 sal_Bool SAL_CALL
ODatabaseMetaData::supportsExpressionsInOrderBy( )
486 sal_Bool SAL_CALL
ODatabaseMetaData::supportsGroupBy( )
491 sal_Bool SAL_CALL
ODatabaseMetaData::supportsGroupByBeyondSelect( )
497 sal_Bool SAL_CALL
ODatabaseMetaData::supportsGroupByUnrelated( )
504 sal_Bool SAL_CALL
ODatabaseMetaData::supportsMultipleResultSets( )
509 sal_Bool SAL_CALL
ODatabaseMetaData::supportsLikeEscapeClause( )
514 sal_Bool SAL_CALL
ODatabaseMetaData::supportsOrderByUnrelated( )
519 sal_Bool SAL_CALL
ODatabaseMetaData::supportsUnion( )
524 sal_Bool SAL_CALL
ODatabaseMetaData::supportsUnionAll( )
529 sal_Bool SAL_CALL
ODatabaseMetaData::nullsAreSortedAtEnd( )
534 sal_Bool SAL_CALL
ODatabaseMetaData::nullsAreSortedAtStart( )
539 sal_Bool SAL_CALL
ODatabaseMetaData::nullsAreSortedHigh( )
544 sal_Bool SAL_CALL
ODatabaseMetaData::nullsAreSortedLow( )
549 sal_Bool SAL_CALL
ODatabaseMetaData::supportsCorrelatedSubqueries( )
554 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSubqueriesInComparisons( )
559 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSubqueriesInExists( )
564 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSubqueriesInIns( )
569 sal_Bool SAL_CALL
ODatabaseMetaData::supportsSubqueriesInQuantifieds( )
574 sal_Bool SAL_CALL
ODatabaseMetaData::supportsANSI92IntermediateSQL( )
579 OUString SAL_CALL
ODatabaseMetaData::getURL()
581 return m_pConnection
->getConnectionURL();
584 OUString SAL_CALL
ODatabaseMetaData::getUserName( )
589 OUString SAL_CALL
ODatabaseMetaData::getDriverName( )
594 OUString SAL_CALL
ODatabaseMetaData::getDriverVersion()
599 OUString SAL_CALL
ODatabaseMetaData::getDatabaseProductVersion( )
601 uno::Reference
< XStatement
> xSelect
= m_pConnection
->createStatement();
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);
609 OUString SAL_CALL
ODatabaseMetaData::getDatabaseProductName( )
611 return "Firebird (engine12)";
614 OUString SAL_CALL
ODatabaseMetaData::getProcedureTerm( )
619 sal_Int32 SAL_CALL
ODatabaseMetaData::getDriverMajorVersion( )
624 sal_Int32 SAL_CALL
ODatabaseMetaData::getDriverMinorVersion( )
629 OUString SAL_CALL
ODatabaseMetaData::getSQLKeywords( )
634 OUString SAL_CALL
ODatabaseMetaData::getSearchStringEscape( )
639 OUString SAL_CALL
ODatabaseMetaData::getStringFunctions( )
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";
646 OUString SAL_CALL
ODatabaseMetaData::getTimeDateFunctions( )
648 return "CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,DATEADD, DATEDIFF,"
649 "EXTRACT,'NOW','TODAY','TOMORROW','YESTERDAY'";
652 OUString SAL_CALL
ODatabaseMetaData::getSystemFunctions( )
657 OUString SAL_CALL
ODatabaseMetaData::getNumericFunctions( )
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";
664 sal_Bool SAL_CALL
ODatabaseMetaData::supportsExtendedSQLGrammar( )
669 sal_Bool SAL_CALL
ODatabaseMetaData::supportsFullOuterJoins( )
674 sal_Bool SAL_CALL
ODatabaseMetaData::supportsLimitedOuterJoins( )
679 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnsInGroupBy( )
681 return 0; // 0 means no limit
684 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnsInOrderBy( )
686 return 0; // 0 means no limit
689 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxColumnsInSelect( )
691 return 0; // 0 means no limit
694 sal_Int32 SAL_CALL
ODatabaseMetaData::getMaxUserNameLength( )
699 sal_Bool SAL_CALL
ODatabaseMetaData::supportsResultSetType(sal_Int32 setType
)
703 case ResultSetType::FORWARD_ONLY
:
710 sal_Bool SAL_CALL
ODatabaseMetaData::supportsResultSetConcurrency(
711 sal_Int32 aResultSetType
,
712 sal_Int32 aConcurrency
)
714 if (aResultSetType
== ResultSetType::FORWARD_ONLY
715 && aConcurrency
== ResultSetConcurrency::READ_ONLY
)
721 sal_Bool SAL_CALL
ODatabaseMetaData::ownUpdatesAreVisible( sal_Int32
)
726 sal_Bool SAL_CALL
ODatabaseMetaData::ownDeletesAreVisible( sal_Int32
)
731 sal_Bool SAL_CALL
ODatabaseMetaData::ownInsertsAreVisible( sal_Int32
)
736 sal_Bool SAL_CALL
ODatabaseMetaData::othersUpdatesAreVisible( sal_Int32
)
741 sal_Bool SAL_CALL
ODatabaseMetaData::othersDeletesAreVisible( sal_Int32
)
746 sal_Bool SAL_CALL
ODatabaseMetaData::othersInsertsAreVisible( sal_Int32
)
751 sal_Bool SAL_CALL
ODatabaseMetaData::updatesAreDetected( sal_Int32
)
756 sal_Bool SAL_CALL
ODatabaseMetaData::deletesAreDetected( sal_Int32
)
761 sal_Bool SAL_CALL
ODatabaseMetaData::insertsAreDetected( sal_Int32
)
766 sal_Bool SAL_CALL
ODatabaseMetaData::supportsBatchUpdates()
768 // No batch support in firebird
772 uno::Reference
< XConnection
> SAL_CALL
ODatabaseMetaData::getConnection()
774 return m_pConnection
;
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
782 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getTableTypes( )
784 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
785 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTableTypes
);
787 ODatabaseMetaDataResultSet::ORows aResults
;
788 ODatabaseMetaDataResultSet::ORow
aRow(2);
790 aRow
[0] = new ORowSetValueDecorator(); // unused
792 // TODO Put these statics to one place
793 // like postgreSQL's Statics class.
795 aRow
[1] = new ORowSetValueDecorator(OUString("TABLE"));
796 aResults
.push_back(aRow
);
798 aRow
[1] = new ORowSetValueDecorator(OUString("VIEW"));
799 aResults
.push_back(aRow
);
801 aRow
[1] = new ORowSetValueDecorator(OUString("SYSTEM TABLE"));
802 aResults
.push_back(aRow
);
804 pResultSet
->setRows(aResults
);
808 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getTypeInfo()
810 SAL_INFO("connectivity.firebird", "getTypeInfo()");
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
= []()
818 ODatabaseMetaDataResultSet::ORows tmp
;
819 ODatabaseMetaDataResultSet::ORow
aRow(19);
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
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
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
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
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
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
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
);
902 // Integer Types common
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
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
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
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
927 // Decimal Types common
929 aRow
[9] = new ORowSetValueDecorator(
930 sal_Int16(ColumnSearch::FULL
)); // Searchable
931 aRow
[12] = new ORowSetValueDecorator(true); // Autoincrement
934 aRow
[6] = new ORowSetValueDecorator(OUString("PRECISION,SCALE")); // Create params
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
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
950 aRow
[6] = new ORowSetValueDecorator(); // Create Params
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
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
966 // TODO: no idea whether D_FLOAT corresponds to an sql type
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
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
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
);
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
);
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
);
1029 pResultSet
->setRows(aResults
);
1033 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getColumnPrivileges(
1034 const Any
& /*aCatalog*/,
1035 const OUString
& /*sSchema*/,
1036 const OUString
& sTable
,
1037 const OUString
& sColumnNamePattern
)
1039 SAL_INFO("connectivity.firebird", "getColumnPrivileges() with "
1041 << " & ColumnNamePattern: " << sColumnNamePattern
);
1043 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1044 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumnPrivileges
);
1045 uno::Reference
< XStatement
> statement
= m_pConnection
->createStatement();
1047 static const char wld
[] = "%";
1048 OUStringBuffer
queryBuf(
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 ");
1059 OUString sAppend
= "WHERE priv.RDB$RELATION_NAME = '%' ";
1060 queryBuf
.append(sAppend
.replaceAll("%", sTable
));
1062 if (!sColumnNamePattern
.isEmpty())
1065 if (sColumnNamePattern
.match(wld
))
1066 sAppend
= "AND priv.RDB$FIELD_NAME LIKE '%' ";
1068 sAppend
= "AND priv.RDB$FIELD_NAME = '%' ";
1070 queryBuf
.append(sAppend
.replaceAll(wld
, sColumnNamePattern
));
1073 queryBuf
.append(" ORDER BY priv.RDB$FIELD, "
1074 "priv.RDB$PRIVILEGE");
1076 OUString query
= queryBuf
.makeStringAndClear();
1078 uno::Reference
< XResultSet
> rs
= statement
->executeQuery(query
);
1079 uno::Reference
< XRow
> xRow( rs
, UNO_QUERY_THROW
);
1080 ODatabaseMetaDataResultSet::ORows aResults
;
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
1090 aCurrentRow
[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(1)));
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
1099 aResults
.push_back(aCurrentRow
);
1102 pResultSet
->setRows( aResults
);
1107 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getColumns(
1108 const Any
& /*catalog*/,
1109 const OUString
& /*schemaPattern*/,
1110 const OUString
& tableNamePattern
,
1111 const OUString
& columnNamePattern
)
1113 SAL_INFO("connectivity.firebird", "getColumns() with "
1114 "TableNamePattern: " << tableNamePattern
<<
1115 " & ColumnNamePattern: " << columnNamePattern
);
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
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) "
1142 if (!tableNamePattern
.isEmpty())
1145 if (tableNamePattern
.match("%"))
1146 sAppend
= "AND relfields.RDB$RELATION_NAME LIKE '%' ";
1148 sAppend
= "AND relfields.RDB$RELATION_NAME = '%' ";
1150 queryBuf
.append(sAppend
.replaceAll("%", tableNamePattern
));
1153 if (!columnNamePattern
.isEmpty())
1156 if (columnNamePattern
.match("%"))
1157 sAppend
= "AND relfields.RDB$FIELD_NAME LIKE '%' ";
1159 sAppend
= "AND relfields.RDB$FIELD_NAME = '%' ";
1161 queryBuf
.append(sAppend
.replaceAll("%", columnNamePattern
));
1164 OUString query
= queryBuf
.makeStringAndClear();
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
);
1170 ODatabaseMetaDataResultSet::ORows aResults
;
1171 ODatabaseMetaDataResultSet::ORow
aCurrentRow(19);
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
1184 aCurrentRow
[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(1)));
1186 aCurrentRow
[4] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(2)));
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
,
1196 aCurrentRow
[5] = new ORowSetValueDecorator(aInfo
.getSdbcType());
1197 // 6. Typename (SQL_*)
1198 aCurrentRow
[6] = new ORowSetValueDecorator(aInfo
.getColumnTypeName());
1202 sal_Int32 aColumnSize
= 0;
1207 aColumnSize
= xRow
->getShort(12);
1216 aColumnSize
= xRow
->getShort(9);
1227 aCurrentRow
[7] = new ORowSetValueDecorator(aColumnSize
);
1230 // 9. Decimal digits (scale)
1231 // fb stores a negative number
1232 aCurrentRow
[9] = new ORowSetValueDecorator( static_cast<sal_Int16
>(-aScale
) );
1235 if (xRow
->getShort(11))
1237 aCurrentRow
[11] = new ORowSetValueDecorator(ColumnValue::NO_NULLS
);
1241 aCurrentRow
[11] = new ORowSetValueDecorator(ColumnValue::NULLABLE
);
1243 // 12. Comments -- may be omitted
1245 OUString aDescription
;
1246 uno::Reference
< XBlob
> xBlob
= xRow
->getBlob(3);
1249 const sal_Int64 aBlobLength
= xBlob
->length();
1250 if (aBlobLength
> SAL_MAX_INT32
)
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()),
1255 RTL_TEXTENCODING_UTF8
);
1259 aDescription
= OUString(reinterpret_cast<char*>(xBlob
->getBytes(1, static_cast<sal_Int32
>(aBlobLength
)).getArray()),
1261 RTL_TEXTENCODING_UTF8
);
1264 aCurrentRow
[12] = new ORowSetValueDecorator(aDescription
);
1266 // 13. Default -- may be omitted.
1268 uno::Reference
< XBlob
> xDefaultValueBlob
= xRow
->getBlob(4);
1269 if (xDefaultValueBlob
.is())
1273 aCurrentRow
[13] = new ORowSetValueDecorator();
1276 // 16. Bytes in Column for char
1277 if (aType
== SQL_TEXT
)
1279 aCurrentRow
[16] = new ORowSetValueDecorator(xRow
->getShort(8));
1281 else if (aType
== SQL_VARYING
)
1283 aCurrentRow
[16] = new ORowSetValueDecorator(sal_Int32(32767));
1287 aCurrentRow
[16] = new ORowSetValueDecorator(sal_Int32(0));
1289 // 17. Index of column
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));
1297 if (xRow
->getShort(9))
1299 aCurrentRow
[18] = new ORowSetValueDecorator(OUString("NO"));
1303 aCurrentRow
[18] = new ORowSetValueDecorator(OUString("YES"));
1306 aResults
.push_back(aCurrentRow
);
1308 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1309 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumns
);
1310 pResultSet
->setRows( aResults
);
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
)
1321 SAL_INFO("connectivity.firebird", "getTables() with "
1322 "TableNamePattern: " << tableNamePattern
);
1324 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1325 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables
);
1326 uno::Reference
< XStatement
> statement
= m_pConnection
->createStatement();
1328 static const char wld
[] = "%";
1329 OUStringBuffer
queryBuf(
1331 "RDB$RELATION_NAME, "
1333 "RDB$RELATION_TYPE, "
1336 "FROM RDB$RELATIONS "
1339 // TODO: GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, SYNONYM
1340 if (!types
.hasElements() || (types
.getLength() == 1 && types
[0].match(wld
)))
1342 // All table types? I.e. includes system tables.
1343 queryBuf
.append("(RDB$RELATION_TYPE = 0 OR RDB$RELATION_TYPE = 1) ");
1347 queryBuf
.append("( (0 = 1) ");
1348 for (OUString
const & t
: types
)
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) ");
1357 throw SQLException(); // TODO: implement other types, see above.
1359 queryBuf
.append(") ");
1362 if (!tableNamePattern
.isEmpty())
1365 if (tableNamePattern
.match(wld
))
1366 sAppend
= "AND RDB$RELATION_NAME LIKE '%' ";
1368 sAppend
= "AND RDB$RELATION_NAME = '%' ";
1370 queryBuf
.append(sAppend
.replaceAll(wld
, tableNamePattern
));
1373 queryBuf
.append(" ORDER BY RDB$RELATION_TYPE, RDB$RELATION_NAME");
1375 OUString query
= queryBuf
.makeStringAndClear();
1377 uno::Reference
< XResultSet
> rs
= statement
->executeQuery(query
);
1378 uno::Reference
< XRow
> xRow( rs
, UNO_QUERY_THROW
);
1379 ODatabaseMetaDataResultSet::ORows aResults
;
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
1389 aCurrentRow
[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(1)));
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
;
1399 if (nSystemFlag
== 1)
1401 sTableType
= "SYSTEM TABLE";
1405 sTableType
= "VIEW";
1409 if (nTableType
== 0)
1410 sTableType
= "TABLE";
1413 aCurrentRow
[4] = new ORowSetValueDecorator(sTableType
);
1417 uno::Reference
< XClob
> xClob
= xRow
->getClob(4);
1420 aCurrentRow
[5] = new ORowSetValueDecorator(xClob
->getSubString(0, xClob
->length()));
1424 aResults
.push_back(aCurrentRow
);
1427 pResultSet
->setRows( aResults
);
1432 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getProcedureColumns(
1433 const Any
&, const OUString
&,
1434 const OUString
&, const OUString
& )
1436 SAL_WARN("connectivity.firebird", "Not yet implemented");
1437 OSL_FAIL("Not implemented yet!");
1439 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedureColumns
);
1442 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getProcedures(
1443 const Any
&, const OUString
&,
1446 SAL_WARN("connectivity.firebird", "Not yet implemented");
1447 OSL_FAIL("Not implemented yet!");
1449 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eProcedures
);
1452 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getVersionColumns(
1453 const Any
&, const OUString
&, const OUString
& )
1455 SAL_WARN("connectivity.firebird", "Not yet implemented");
1456 OSL_FAIL("Not implemented yet!");
1458 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eVersionColumns
);
1461 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getExportedKeys(
1462 const Any
&, const OUString
&, const OUString
& table
)
1464 return ODatabaseMetaData::lcl_getKeys(false, table
);
1467 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getImportedKeys(
1468 const Any
&, const OUString
&, const OUString
& table
)
1470 return ODatabaseMetaData::lcl_getKeys(true, table
);
1473 uno::Reference
< XResultSet
> ODatabaseMetaData::lcl_getKeys(const bool bIsImport
, std::u16string_view table
)
1475 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1476 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eImportedKeys
);
1478 uno::Reference
< XStatement
> statement
= m_pConnection
->createStatement();
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' ";
1503 sSQL
+= OUString::Concat("AND FOREI.RDB$RELATION_NAME = '")+ table
+"'";
1505 sSQL
+= OUString::Concat("AND PRIM.RDB$RELATION_NAME = '")+ table
+"'";
1507 uno::Reference
< XResultSet
> rs
= statement
->executeQuery(sSQL
);
1508 uno::Reference
< XRow
> xRow( rs
, UNO_QUERY_THROW
);
1510 ODatabaseMetaDataResultSet::ORows aResults
;
1511 ODatabaseMetaDataResultSet::ORow
aCurrentRow(15);
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
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
;
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
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
1538 aCurrentRow
[12] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(4))); // FK name
1539 aCurrentRow
[13] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(3))); // PK name
1541 aCurrentRow
[14] = new ORowSetValueDecorator(Deferrability::NONE
); // deferrability
1543 // deferrability is currently not supported, but may be supported in the future.
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));
1552 aResults
.push_back(aCurrentRow
);
1555 pResultSet
->setRows( aResults
);
1559 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getPrimaryKeys(
1560 const Any
& /*aCatalog*/,
1561 const OUString
& /*sSchema*/,
1562 const OUString
& sTable
)
1564 SAL_INFO("connectivity.firebird", "getPrimaryKeys() with "
1565 "Table: " << sTable
);
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";
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
);
1584 ODatabaseMetaDataResultSet::ORows aResults
;
1585 ODatabaseMetaDataResultSet::ORow
aCurrentRow(7);
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
1594 if (xRs
->getRow() == 1) // Table name doesn't change, so only retrieve once
1596 aCurrentRow
[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(1)));
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)));
1605 aResults
.push_back(aCurrentRow
);
1607 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1608 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys
);
1609 pResultSet
->setRows( aResults
);
1614 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getIndexInfo(
1615 const Any
& /*aCatalog*/,
1616 const OUString
& /*sSchema*/,
1617 const OUString
& sTable
,
1619 sal_Bool
) // TODO: what is bIsApproximate?
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
);
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.
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
1647 aQueryBuf
.append("AND (indices.RDB$UNIQUE_FLAG = 1) ");
1649 OUString sQuery
= aQueryBuf
.makeStringAndClear();
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
);
1655 ODatabaseMetaDataResultSet::ORows aResults
;
1656 ODatabaseMetaDataResultSet::ORow
aCurrentRow(14);
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
1673 if (xRs
->getRow() == 1) // Table name doesn't change, so only retrieve once
1675 aCurrentRow
[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(1)));
1678 // 4. NON_UNIQUE -- i.e. specifically negate here.
1679 aCurrentRow
[4] = new ORowSetValueDecorator(xRow
->getShort(5) == 0);
1681 aCurrentRow
[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow
->getString(4)));
1683 // 8. ORDINAL POSITION
1684 aCurrentRow
[8] = new ORowSetValueDecorator(xRow
->getShort(3));
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"));
1691 aCurrentRow
[10] = new ORowSetValueDecorator(OUString("A"));
1692 // TODO: double check this^^^, doesn't seem to be officially documented anywhere.
1694 aCurrentRow
[11] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this
1696 aCurrentRow
[12] = new ORowSetValueDecorator(sal_Int32(0)); // TODO: determine how to do this
1698 aResults
.push_back(aCurrentRow
);
1700 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1701 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys
);
1702 pResultSet
->setRows( aResults
);
1707 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getBestRowIdentifier(
1708 const Any
&, const OUString
&, const OUString
&, sal_Int32
,
1711 OSL_FAIL("Not implemented yet!");
1713 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eBestRowIdentifier
);
1716 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getTablePrivileges(
1717 const Any
& /*aCatalog*/,
1718 const OUString
& /*sSchemaPattern*/,
1719 const OUString
& sTableNamePattern
)
1721 SAL_INFO("connectivity.firebird", "getTablePrivileges() with "
1722 "TableNamePattern: " << sTableNamePattern
);
1724 rtl::Reference
<ODatabaseMetaDataResultSet
> pResultSet
= new
1725 ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTablePrivileges
);
1726 uno::Reference
< XStatement
> statement
= m_pConnection
->createStatement();
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(
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 ");
1740 if (!sTableNamePattern
.isEmpty())
1743 if (sTableNamePattern
.match(wld
))
1744 sAppend
= "WHERE priv.RDB$RELATION_NAME LIKE '%' ";
1746 sAppend
= "WHERE priv.RDB$RELATION_NAME = '%' ";
1748 queryBuf
.append(sAppend
.replaceAll(wld
, sTableNamePattern
));
1750 queryBuf
.append(" ORDER BY priv.RDB$RELATION_TYPE, "
1751 "priv.RDB$RELATION_NAME, "
1752 "priv.RDB$PRIVILEGE");
1754 OUString query
= queryBuf
.makeStringAndClear();
1756 uno::Reference
< XResultSet
> rs
= statement
->executeQuery(query
);
1757 uno::Reference
< XRow
> xRow( rs
, UNO_QUERY_THROW
);
1758 ODatabaseMetaDataResultSet::ORows aResults
;
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.
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
1774 aResults
.push_back(aRow
);
1777 pResultSet
->setRows( aResults
);
1782 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getCrossReference(
1783 const Any
&, const OUString
&,
1784 const OUString
&, const Any
&,
1785 const OUString
&, const OUString
& )
1787 OSL_FAIL("Not implemented yet!");
1789 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eCrossReference
);
1792 uno::Reference
< XResultSet
> SAL_CALL
ODatabaseMetaData::getUDTs( const Any
&, const OUString
&, const OUString
&, const Sequence
< sal_Int32
>& )
1794 OSL_FAIL("Not implemented yet!");
1796 return new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eUDTs
);
1799 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */