[Libreoffice-commits] core.git: 4 commits - connectivity/source
Andrzej J.R. Hunt
andrzej at ahunt.org
Thu Sep 5 05:48:38 PDT 2013
connectivity/source/drivers/firebird/Connection.cxx | 65 ++++++++
connectivity/source/drivers/firebird/Connection.hxx | 8 +
connectivity/source/drivers/firebird/DatabaseMetaData.cxx | 102 ++++++++++++--
3 files changed, 166 insertions(+), 9 deletions(-)
New commits:
commit 748bf45544a31b7bd6217d046009e272d11aa310
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date: Fri Sep 6 12:50:25 2013 +0100
Actually use table name in getIndexInfo. (firebird-sdbc)
Otherwise dbaccess's indexcollection gets confused and can segfault
when indexes not belonging to the desired table are returned.
Change-Id: I4dfe62bf1053c65cac907bf490749ee2cc24e6ca
diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
index ddb9ea4..0f86ad5 100644
--- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
+++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
@@ -1575,7 +1575,8 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getIndexInfo(
"FROM RDB$INDICES indices "
"JOIN RDB$INDEX_SEGMENTS index_segments "
"on (indices.RDB$INDEX_NAME = index_segments.RDB$INDEX_NAME) "
- "WHERE (indices.RDB$SYSTEM_FLAG = 0) ");
+ "WHERE indices.RDB$RELATION_NAME = '" + sTable + "' "
+ "AND (indices.RDB$SYSTEM_FLAG = 0) ");
// Not sure whether we should exclude system indices, but otoh. we never
// actually deal with system tables (system indices only apply to system
// tables) within the GUI.
commit 2e31c305a374f14d927ea700657a85aa705f21d9
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date: Fri Sep 6 11:47:49 2013 +0100
Actually rebuild indexes in rebuildIndexes. (firebird-sdbc)
Change-Id: I76ac3b261bce830879f17e82ddd22a9f4d957f11
diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx
index 5cca811..cb935c9 100644
--- a/connectivity/source/drivers/firebird/Connection.cxx
+++ b/connectivity/source/drivers/firebird/Connection.cxx
@@ -792,12 +792,13 @@ uno::Reference< XTablesSupplier > OConnection::createCatalog()
void OConnection::rebuildIndexes() throw(SQLException)
{
-
SAL_INFO("connectivity.firebird", "rebuildIndexes()");
MutexGuard aGuard(m_aMutex);
// We only need to do this for character based columns on user-created tables.
+ // Ideally we'd use a FOR SELECT ... INTO .... DO ..., but that seems to
+ // only be possible using PSQL, i.e. using a stored procedure.
OUString sSql(
// multiple columns possible per index, only select once
"SELECT DISTINCT indices.RDB$INDEX_NAME "
@@ -816,15 +817,35 @@ void OConnection::rebuildIndexes() throw(SQLException)
"AND (indices.RDB$INDEX_INACTIVE IS NULL OR indices.RDB$INDEX_INACTIVE = 0) "
);
+ uno::Reference< XStatement > xCharIndicesStatement = createStatement();
+ uno::Reference< XResultSet > xCharIndices =
+ xCharIndicesStatement->executeQuery(sSql);
+ uno::Reference< XRow > xRow(xCharIndices, UNO_QUERY_THROW);
+
+ uno::Reference< XStatement > xAlterIndexStatement = createStatement();
- uno::Reference< XStatement > xStatement = createStatement();
- uno::Reference< XResultSet > xCharIndices = xStatement->executeQuery(sSql);
- uno::Reference< XRow > xRow( xCharIndices, UNO_QUERY_THROW );
+ // ALTER is a DDL statement, hence using Statement will cause a commit
+ // after every alter -- in this case this is inappropriate (xCharIndicesStatement
+ // and its ResultSet become invalidated) hence we use the native api.
while (xCharIndices->next())
{
+ OUString sIndexName(xRow->getString(1));
+ SAL_INFO("connectivity.firebird", "rebuilding index " + sIndexName);
+ OString sAlterIndex = "ALTER INDEX "
+ + OUStringToOString(sIndexName, RTL_TEXTENCODING_UTF8)
+ + " ACTIVE";
+
+ ISC_STATUS_ARRAY aStatusVector;
+ ISC_STATUS aErr = 0;
+
+ aErr = isc_dsql_execute_immediate(aStatusVector,
+ &getDBHandle(),
+ &getTransaction(),
+ 0, // Length: 0 for null terminated
+ sAlterIndex.getStr(),
+ FIREBIRD_SQL_DIALECT,
+ NULL);
}
-
- Reference< XCloseable> xClose(xCharIndices,UNO_QUERY);
- xClose->close();
+ commit();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4ef1215d6a380b05bb8bb8d6fca869ac7eca05ff
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date: Fri Sep 6 10:55:40 2013 +0100
Retrieve all char indexes for rebuildIndexes. (firebird-sdbc)
This provides the SQL SELECT statement necessary to retrieve all the indexes
needing rebuilding.
Change-Id: I07661277682f83dc3f2d33a398abd83593c9928d
diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx
index de795eb..5cca811 100644
--- a/connectivity/source/drivers/firebird/Connection.cxx
+++ b/connectivity/source/drivers/firebird/Connection.cxx
@@ -274,6 +274,12 @@ void OConnection::construct(const ::rtl::OUString& url, const Sequence< Property
if (m_bIsEmbedded) // Add DocumentEventListener to save the .fdb as needed
{
+ // TODO: this is only needed when we change icu versions, so ideally
+ // we somehow keep track of which icu version we have. There might
+ // be something db internal that we can check, or we might have to store
+ // it in the .odb.
+ rebuildIndexes();
+
uno::Reference< frame::XDesktop2 > xFramesSupplier =
frame::Desktop::create(::comphelper::getProcessComponentContext());
uno::Reference< frame::XFrames > xFrames( xFramesSupplier->getFrames(),
@@ -783,4 +789,42 @@ uno::Reference< XTablesSupplier > OConnection::createCatalog()
}
}
+
+void OConnection::rebuildIndexes() throw(SQLException)
+{
+
+ SAL_INFO("connectivity.firebird", "rebuildIndexes()");
+ MutexGuard aGuard(m_aMutex);
+
+ // We only need to do this for character based columns on user-created tables.
+
+ OUString sSql(
+ // multiple columns possible per index, only select once
+ "SELECT DISTINCT indices.RDB$INDEX_NAME "
+ "FROM RDB$INDICES indices "
+ "JOIN RDB$INDEX_SEGMENTS index_segments "
+ "ON (indices.RDB$INDEX_NAME = index_segments.RDB$INDEX_NAME) "
+ "JOIN RDB$RELATION_FIELDS relation_fields "
+ "ON (index_segments.RDB$FIELD_NAME = relation_fields.RDB$FIELD_NAME) "
+ "JOIN RDB$FIELDS fields "
+ "ON (relation_fields.RDB$FIELD_SOURCE = fields.RDB$FIELD_NAME) "
+
+ "WHERE (indices.RDB$SYSTEM_FLAG = 0) "
+ // TODO: what about blr_text2 etc. ?
+ "AND ((fields.RDB$FIELD_TYPE = " + OUString::number((int) blr_text) + ") "
+ " OR (fields.RDB$FIELD_TYPE = " + OUString::number((int) blr_varying) + ")) "
+ "AND (indices.RDB$INDEX_INACTIVE IS NULL OR indices.RDB$INDEX_INACTIVE = 0) "
+ );
+
+
+ uno::Reference< XStatement > xStatement = createStatement();
+ uno::Reference< XResultSet > xCharIndices = xStatement->executeQuery(sSql);
+ uno::Reference< XRow > xRow( xCharIndices, UNO_QUERY_THROW );
+ while (xCharIndices->next())
+ {
+ }
+
+ Reference< XCloseable> xClose(xCharIndices,UNO_QUERY);
+ xClose->close();
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/firebird/Connection.hxx b/connectivity/source/drivers/firebird/Connection.hxx
index 4d7658d..cdf6c44 100644
--- a/connectivity/source/drivers/firebird/Connection.hxx
+++ b/connectivity/source/drivers/firebird/Connection.hxx
@@ -112,6 +112,14 @@ namespace connectivity
::com::sun::star::uno::WeakReference< ::com::sun::star::sdbcx::XTablesSupplier>
m_xCatalog;
+
+ /**
+ * Firebird stores binary collations for indexes on Character based
+ * columns, these can be binary-incompatible between different icu
+ * version, hence we need to rebuild the indexes when switching icu
+ * versions.
+ */
+ void rebuildIndexes() throw( ::com::sun::star::sdbc::SQLException);
void buildTypeInfo() throw( ::com::sun::star::sdbc::SQLException);
void setupTransaction() throw(::com::sun::star::sdbc::SQLException);
commit 17a2a19ca23c0e3acf6dadc5ccdad054395738ef
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date: Thu Sep 5 08:20:43 2013 +0100
Implement getIndexInfo. (firebird-sdbc)
Change-Id: I8c3393fbc7c4fb418f31a80b23360c6c7bf21a25
diff --git a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
index 2eabddf..ddb9ea4 100644
--- a/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
+++ b/connectivity/source/drivers/firebird/DatabaseMetaData.cxx
@@ -26,6 +26,7 @@
#include <com/sun/star/sdbc/ColumnValue.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/IndexType.hpp>
#include <com/sun/star/sdbc/ResultSetType.hpp>
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
#include <com/sun/star/sdbc/TransactionIsolation.hpp>
@@ -1548,17 +1549,99 @@ uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getPrimaryKeys(
return xResultSet;
}
-// -------------------------------------------------------------------------
+
uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getIndexInfo(
- const Any& catalog, const OUString& schema, const OUString& table,
- sal_Bool unique, sal_Bool approximate ) throw(SQLException, RuntimeException)
+ const Any& aCatalog, const OUString& sSchema, const OUString& sTable,
+ sal_Bool bIsUnique, sal_Bool bIsApproximate)
+ throw(SQLException, RuntimeException)
{
- (void) catalog;
- (void) schema;
- (void) table;
- (void) unique;
- (void) approximate;
- return NULL;
+ (void) aCatalog;
+ (void) sSchema;
+
+ // Apparently this method can also return a "tableIndexStatistic"
+ // However this is only mentioned in XDatabaseMetaData.idl (whose comments
+ // are duplicated in the postgresql driver), and is otherwise undocumented.
+
+ SAL_INFO("connectivity.firebird", "getPrimaryKeys() with "
+ "Table: " << sTable);
+
+ OUStringBuffer aQueryBuf("SELECT "
+ "indices.RDB$RELATION_NAME, " // 1. Table Name
+ "index_segments.RDB$FIELD_NAME, " // 2. Column Name
+ "index_segments.RDB$FIELD_POSITION, " // 3. Sequence Number
+ "indices.RDB$INDEX_NAME, " // 4. Index name
+ "indices.RDB$UNIQUE_FLAG, " // 5. Unique Flag
+ "indices.RDB$INDEX_TYPE " // 6. Index Type
+ "FROM RDB$INDICES indices "
+ "JOIN RDB$INDEX_SEGMENTS index_segments "
+ "on (indices.RDB$INDEX_NAME = index_segments.RDB$INDEX_NAME) "
+ "WHERE (indices.RDB$SYSTEM_FLAG = 0) ");
+ // Not sure whether we should exclude system indices, but otoh. we never
+ // actually deal with system tables (system indices only apply to system
+ // tables) within the GUI.
+
+ // Only filter if true (according to the docs), i.e.:
+ // If false we return all indices, if true we return only unique indices
+ if (bIsUnique)
+ aQueryBuf.append("AND (indices.RDB$UNIQUE_FLAG = 1) ");
+
+ // TODO: what is bIsApproximate?
+ (void) bIsApproximate;
+
+ OUString sQuery = aQueryBuf.makeStringAndClear();
+
+ uno::Reference< XStatement > xStatement = m_pConnection->createStatement();
+ uno::Reference< XResultSet > xRs = xStatement->executeQuery(sQuery);
+ uno::Reference< XRow > xRow( xRs, UNO_QUERY_THROW );
+
+ ODatabaseMetaDataResultSet::ORows aResults;
+ ODatabaseMetaDataResultSet::ORow aCurrentRow(14);
+
+ aCurrentRow[0] = new ORowSetValueDecorator(); // Unused -- numbering starts from 0
+ aCurrentRow[1] = new ORowSetValueDecorator(); // Catalog - can be null
+ aCurrentRow[2] = new ORowSetValueDecorator(); // Schema - can be null
+ aCurrentRow[5] = new ORowSetValueDecorator(); // Index Catalog -- can be null
+ // According to wikipedia firebird uses clustered indices.
+ // The documentation does not specifically seem to specify this.
+ aCurrentRow[7] = new ORowSetValueDecorator(IndexType::CLUSTERED); // 7. INDEX TYPE
+ aCurrentRow[13] = new ORowSetValueDecorator(); // Filter Condition -- can be null
+
+ while(xRs->next())
+ {
+ // 3. Table Name
+ if (xRs->getRow() == 1) // Table name doesn't change, so only retrieve once
+ {
+ aCurrentRow[3] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(1)));
+ }
+
+ // 4. NON_UNIQUE -- i.e. specifically negate here.
+ aCurrentRow[4] = new ORowSetValueDecorator(!xRow->getBoolean(5));
+ // 6. INDEX NAME
+ aCurrentRow[6] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(4)));
+
+ // 8. ORDINAL POSITION
+ aCurrentRow[8] = new ORowSetValueDecorator(xRow->getShort(3));
+ // 9. COLUMN NAME
+ aCurrentRow[9] = new ORowSetValueDecorator(sanitizeIdentifier(xRow->getString(2)));
+ // 10. ASC(ending)/DESC(ending)
+ if (xRow->getShort(6) == 1)
+ aCurrentRow[10] = new ORowSetValueDecorator(OUString("D"));
+ else
+ aCurrentRow[10] = new ORowSetValueDecorator(OUString("A"));
+ // TODO: double check this^^^, doesn't seem to be officially documented anywhere.
+ // 11. CARDINALITY
+ aCurrentRow[11] = new ORowSetValueDecorator((sal_Int32)0); // TODO: determine how to do this
+ // 12. PAGES
+ aCurrentRow[12] = new ORowSetValueDecorator((sal_Int32)0); // TODO: determine how to do this
+
+ aResults.push_back(aCurrentRow);
+ }
+ ODatabaseMetaDataResultSet* pResultSet = new
+ ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::ePrimaryKeys);
+ uno::Reference< XResultSet > xResultSet = pResultSet;
+ pResultSet->setRows( aResults );
+
+ return xResultSet;
}
// -------------------------------------------------------------------------
uno::Reference< XResultSet > SAL_CALL ODatabaseMetaData::getBestRowIdentifier(
More information about the Libreoffice-commits
mailing list