/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace com::sun::star::text { class XTextDocument; } using namespace ::com::sun::star; static void lcl_GetDataArea(const uno::Reference& xTable, sal_Int32& rColumnCount, sal_Int32& rRowCount) { uno::Reference xColumns = xTable->getColumns(); if (xColumns.is()) rColumnCount = xColumns->getCount(); uno::Reference xRows = xTable->getRows(); if (xRows.is()) rRowCount = xRows->getCount() - 1; // first row (headers) is not counted } static void lcl_GetColumnInfo(const uno::Reference& xTable, sal_Int32 nDocColumn, bool bHasHeaders, OUString& rName, sal_Int32& rDataType, bool& rCurrency) { uno::Reference xCellRange(xTable, uno::UNO_QUERY); // get column name from first row, if range contains headers if (bHasHeaders) { uno::Reference xHeaderText( xCellRange->getCellByPosition(nDocColumn, /*nStartRow*/ 0), uno::UNO_QUERY); if (xHeaderText.is()) rName = xHeaderText->getString(); } rCurrency = false; rDataType = sdbc::DataType::VARCHAR; } static void lcl_SetValue(connectivity::ORowSetValue& rValue, const uno::Reference& xTable, sal_Int32 nStartCol, bool bHasHeaders, sal_Int32 nDBRow, sal_Int32 nDBColumn) { sal_Int32 nDocColumn = nStartCol + nDBColumn - 1; // database counts from 1 sal_Int32 nDocRow = nDBRow - 1; if (bHasHeaders) ++nDocRow; uno::Reference xCellRange(xTable, uno::UNO_QUERY); uno::Reference xCell; try { xCell = xCellRange->getCellByPosition(nDocColumn, nDocRow); } catch (const lang::IndexOutOfBoundsException& /*rException*/) { SAL_WARN("connectivity.writer", "getCellByPosition(" << nDocColumn << ", " << nDocRow << ") failed"); rValue = OUString(); } if (xCell.is()) { const uno::Reference xText(xCell, uno::UNO_QUERY); if (xText.is()) rValue = xText->getString(); } } namespace connectivity::writer { void OWriterTable::fillColumns() { if (!m_xTable.is()) throw sdbc::SQLException(); OUString aTypeName; ::comphelper::UStringMixEqual aCase( m_pConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers()); const bool bStoresMixedCaseQuotedIdentifiers = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers(); for (sal_Int32 i = 0; i < m_nDataCols; i++) { OUString aColumnName; sal_Int32 eType = sdbc::DataType::OTHER; bool bCurrency = false; lcl_GetColumnInfo(m_xTable, m_nStartCol + i, m_bHasHeaders, aColumnName, eType, bCurrency); sal_Int32 nPrecision = 0; //! ... sal_Int32 nDecimals = 0; //! ... switch (eType) { case sdbc::DataType::VARCHAR: aTypeName = "VARCHAR"; break; case sdbc::DataType::DECIMAL: aTypeName = "DECIMAL"; break; case sdbc::DataType::BIT: aTypeName = "BOOL"; break; case sdbc::DataType::DATE: aTypeName = "DATE"; break; case sdbc::DataType::TIME: aTypeName = "TIME"; break; case sdbc::DataType::TIMESTAMP: aTypeName = "TIMESTAMP"; break; default: SAL_WARN("connectivity.writer", "missing type name"); aTypeName.clear(); } // check if the column name already exists OUString aAlias = aColumnName; auto aFind = connectivity::find(m_aColumns->begin(), m_aColumns->end(), aAlias, aCase); sal_Int32 nExprCnt = 0; while (aFind != m_aColumns->end()) { aAlias = aColumnName + OUString::number(++nExprCnt); aFind = connectivity::find(m_aColumns->begin(), m_aColumns->end(), aAlias, aCase); } rtl::Reference pColumn = new sdbcx::OColumn( aAlias, aTypeName, OUString(), OUString(), sdbc::ColumnValue::NULLABLE, nPrecision, nDecimals, eType, false, false, bCurrency, bStoresMixedCaseQuotedIdentifiers, m_CatalogName, getSchema(), getName()); m_aColumns->push_back(pColumn); } } OWriterTable::OWriterTable(sdbcx::OCollection* _pTables, OWriterConnection* _pConnection, const OUString& Name, const OUString& Type) : OWriterTable_BASE(_pTables, _pConnection, Name, Type, OUString() /*Description*/, OUString() /*SchemaName*/, OUString() /*CatalogName*/) , m_pWriterConnection(_pConnection) { } void OWriterTable::construct() { uno::Reference xDoc = m_pWriterConnection->acquireDoc(); if (xDoc.is()) { uno::Reference xTextTablesSupplier(xDoc, uno::UNO_QUERY); uno::Reference xTables = xTextTablesSupplier->getTextTables(); if (xTables.is() && xTables->hasByName(m_Name)) { m_xTable.set(xTables->getByName(m_Name), uno::UNO_QUERY); if (m_xTable.is()) { lcl_GetDataArea(m_xTable, m_nDataCols, m_nDataRows); m_bHasHeaders = true; } } } fillColumns(); refreshColumns(); } void SAL_CALL OWriterTable::disposing() { OFileTable::disposing(); ::osl::MutexGuard aGuard(m_aMutex); m_aColumns = nullptr; if (m_pWriterConnection) m_pWriterConnection->releaseDoc(); m_pWriterConnection = nullptr; } bool OWriterTable::fetchRow(OValueRefRow& _rRow, const OSQLColumns& _rCols, bool bRetrieveData) { // read the bookmark _rRow->setDeleted(false); *(*_rRow)[0] = m_nFilePos; if (!bRetrieveData) return true; // fields const OValueRefVector::size_type nCount = std::min(_rRow->size(), _rCols.size() + 1); for (OValueRefVector::size_type i = 1; i < nCount; i++) { if ((*_rRow)[i]->isBound()) { lcl_SetValue((*_rRow)[i]->get(), m_xTable, m_nStartCol, m_bHasHeaders, m_nFilePos, i); } } return true; } } // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */