1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <writer/WTable.hxx>
21 #include <com/sun/star/sdbc/ColumnValue.hpp>
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <com/sun/star/sdbc/SQLException.hpp>
24 #include <com/sun/star/text/XTextDocument.hpp>
25 #include <com/sun/star/text/XTextTable.hpp>
26 #include <com/sun/star/text/XTextTablesSupplier.hpp>
27 #include <com/sun/star/table/XCellRange.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <writer/WConnection.hxx>
31 #include <connectivity/sdbcx/VColumn.hxx>
32 #include <sal/log.hxx>
33 #include <comphelper/servicehelper.hxx>
34 #include <cppuhelper/typeprovider.hxx>
36 namespace com::sun::star::text
41 using namespace ::com::sun::star
;
43 static void lcl_GetDataArea(const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32
& rColumnCount
,
46 uno::Reference
<container::XIndexAccess
> xColumns
= xTable
->getColumns();
48 rColumnCount
= xColumns
->getCount();
50 uno::Reference
<container::XIndexAccess
> xRows
= xTable
->getRows();
52 rRowCount
= xRows
->getCount() - 1; // first row (headers) is not counted
55 static void lcl_GetColumnInfo(const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32 nDocColumn
,
56 bool bHasHeaders
, OUString
& rName
, sal_Int32
& rDataType
,
59 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
60 // get column name from first row, if range contains headers
63 uno::Reference
<text::XText
> xHeaderText(
64 xCellRange
->getCellByPosition(nDocColumn
, /*nStartRow*/ 0), uno::UNO_QUERY
);
66 rName
= xHeaderText
->getString();
70 rDataType
= sdbc::DataType::VARCHAR
;
73 static void lcl_SetValue(connectivity::ORowSetValue
& rValue
,
74 const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32 nStartCol
,
75 bool bHasHeaders
, sal_Int32 nDBRow
, sal_Int32 nDBColumn
)
77 sal_Int32 nDocColumn
= nStartCol
+ nDBColumn
- 1; // database counts from 1
78 sal_Int32 nDocRow
= nDBRow
- 1;
82 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
83 uno::Reference
<table::XCell
> xCell
;
86 xCell
= xCellRange
->getCellByPosition(nDocColumn
, nDocRow
);
88 catch (const lang::IndexOutOfBoundsException
& /*rException*/)
90 SAL_WARN("connectivity.writer",
91 "getCellByPosition(" << nDocColumn
<< ", " << nDocRow
<< ") failed");
97 const uno::Reference
<text::XText
> xText(xCell
, uno::UNO_QUERY
);
99 rValue
= xText
->getString();
103 namespace connectivity::writer
105 void OWriterTable::fillColumns()
108 throw sdbc::SQLException();
111 ::comphelper::UStringMixEqual
aCase(
112 m_pConnection
->getMetaData()->supportsMixedCaseQuotedIdentifiers());
113 const bool bStoresMixedCaseQuotedIdentifiers
114 = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
116 for (sal_Int32 i
= 0; i
< m_nDataCols
; i
++)
118 OUString aColumnName
;
119 sal_Int32 eType
= sdbc::DataType::OTHER
;
120 bool bCurrency
= false;
122 lcl_GetColumnInfo(m_xTable
, m_nStartCol
+ i
, m_bHasHeaders
, aColumnName
, eType
, bCurrency
);
124 sal_Int32 nPrecision
= 0; //! ...
125 sal_Int32 nDecimals
= 0; //! ...
129 case sdbc::DataType::VARCHAR
:
130 aTypeName
= "VARCHAR";
132 case sdbc::DataType::DECIMAL
:
133 aTypeName
= "DECIMAL";
135 case sdbc::DataType::BIT
:
138 case sdbc::DataType::DATE
:
141 case sdbc::DataType::TIME
:
144 case sdbc::DataType::TIMESTAMP
:
145 aTypeName
= "TIMESTAMP";
148 SAL_WARN("connectivity.writer", "missing type name");
152 // check if the column name already exists
153 OUString aAlias
= aColumnName
;
154 auto aFind
= connectivity::find(m_aColumns
->begin(), m_aColumns
->end(), aAlias
, aCase
);
155 sal_Int32 nExprCnt
= 0;
156 while (aFind
!= m_aColumns
->end())
158 aAlias
= aColumnName
+ OUString::number(++nExprCnt
);
159 aFind
= connectivity::find(m_aColumns
->begin(), m_aColumns
->end(), aAlias
, aCase
);
162 rtl::Reference
<sdbcx::OColumn
> pColumn
= new sdbcx::OColumn(
163 aAlias
, aTypeName
, OUString(), OUString(), sdbc::ColumnValue::NULLABLE
, nPrecision
,
164 nDecimals
, eType
, false, false, bCurrency
, bStoresMixedCaseQuotedIdentifiers
,
165 m_CatalogName
, getSchema(), getName());
166 m_aColumns
->push_back(pColumn
);
170 OWriterTable::OWriterTable(sdbcx::OCollection
* _pTables
, OWriterConnection
* _pConnection
,
171 const OUString
& Name
, const OUString
& Type
)
172 : OWriterTable_BASE(_pTables
, _pConnection
, Name
, Type
, OUString() /*Description*/,
173 OUString() /*SchemaName*/, OUString() /*CatalogName*/)
174 , m_pWriterConnection(_pConnection
)
177 , m_bHasHeaders(false)
181 void OWriterTable::construct()
183 uno::Reference
<text::XTextDocument
> xDoc
= m_pWriterConnection
->acquireDoc();
186 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(xDoc
, uno::UNO_QUERY
);
187 uno::Reference
<container::XNameAccess
> xTables
= xTextTablesSupplier
->getTextTables();
188 if (xTables
.is() && xTables
->hasByName(m_Name
))
190 m_xTable
.set(xTables
->getByName(m_Name
), uno::UNO_QUERY
);
193 lcl_GetDataArea(m_xTable
, m_nDataCols
, m_nDataRows
);
194 m_bHasHeaders
= true;
204 void SAL_CALL
OWriterTable::disposing()
206 OFileTable::disposing();
207 ::osl::MutexGuard
aGuard(m_aMutex
);
208 m_aColumns
= nullptr;
209 if (m_pWriterConnection
)
210 m_pWriterConnection
->releaseDoc();
211 m_pWriterConnection
= nullptr;
214 uno::Sequence
<sal_Int8
> OWriterTable::getUnoTunnelId()
216 static ::cppu::OImplementationId implId
;
218 return implId
.getImplementationId();
221 sal_Int64
OWriterTable::getSomething(const uno::Sequence
<sal_Int8
>& rId
)
223 return (isUnoTunnelId
<OWriterTable
>(rId
)) ? reinterpret_cast<sal_Int64
>(this)
224 : OWriterTable_BASE::getSomething(rId
);
227 bool OWriterTable::fetchRow(OValueRefRow
& _rRow
, const OSQLColumns
& _rCols
, bool bRetrieveData
)
231 _rRow
->setDeleted(false);
232 *(*_rRow
)[0] = m_nFilePos
;
239 const OValueRefVector::size_type nCount
= std::min(_rRow
->size(), _rCols
.size() + 1);
240 for (OValueRefVector::size_type i
= 1; i
< nCount
; i
++)
242 if ((*_rRow
)[i
]->isBound())
244 lcl_SetValue((*_rRow
)[i
]->get(), m_xTable
, m_nStartCol
, m_bHasHeaders
, m_nFilePos
, i
);
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */