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>
34 namespace com::sun::star::text
39 using namespace ::com::sun::star
;
41 static void lcl_GetDataArea(const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32
& rColumnCount
,
44 uno::Reference
<container::XIndexAccess
> xColumns
= xTable
->getColumns();
46 rColumnCount
= xColumns
->getCount();
48 uno::Reference
<container::XIndexAccess
> xRows
= xTable
->getRows();
50 rRowCount
= xRows
->getCount() - 1; // first row (headers) is not counted
53 static void lcl_GetColumnInfo(const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32 nDocColumn
,
54 bool bHasHeaders
, OUString
& rName
, sal_Int32
& rDataType
,
57 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
58 // get column name from first row, if range contains headers
61 uno::Reference
<text::XText
> xHeaderText(
62 xCellRange
->getCellByPosition(nDocColumn
, /*nStartRow*/ 0), uno::UNO_QUERY
);
64 rName
= xHeaderText
->getString();
68 rDataType
= sdbc::DataType::VARCHAR
;
71 static void lcl_SetValue(connectivity::ORowSetValue
& rValue
,
72 const uno::Reference
<text::XTextTable
>& xTable
, sal_Int32 nStartCol
,
73 bool bHasHeaders
, sal_Int32 nDBRow
, sal_Int32 nDBColumn
)
75 sal_Int32 nDocColumn
= nStartCol
+ nDBColumn
- 1; // database counts from 1
76 sal_Int32 nDocRow
= nDBRow
- 1;
80 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
81 uno::Reference
<table::XCell
> xCell
;
84 xCell
= xCellRange
->getCellByPosition(nDocColumn
, nDocRow
);
86 catch (const lang::IndexOutOfBoundsException
& /*rException*/)
88 SAL_WARN("connectivity.writer",
89 "getCellByPosition(" << nDocColumn
<< ", " << nDocRow
<< ") failed");
95 const uno::Reference
<text::XText
> xText(xCell
, uno::UNO_QUERY
);
97 rValue
= xText
->getString();
101 namespace connectivity::writer
103 void OWriterTable::fillColumns()
106 throw sdbc::SQLException();
109 ::comphelper::UStringMixEqual
aCase(
110 m_pConnection
->getMetaData()->supportsMixedCaseQuotedIdentifiers());
111 const bool bStoresMixedCaseQuotedIdentifiers
112 = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
114 for (sal_Int32 i
= 0; i
< m_nDataCols
; i
++)
116 OUString aColumnName
;
117 sal_Int32 eType
= sdbc::DataType::OTHER
;
118 bool bCurrency
= false;
120 lcl_GetColumnInfo(m_xTable
, m_nStartCol
+ i
, m_bHasHeaders
, aColumnName
, eType
, bCurrency
);
122 sal_Int32 nPrecision
= 0; //! ...
123 sal_Int32 nDecimals
= 0; //! ...
127 case sdbc::DataType::VARCHAR
:
128 aTypeName
= "VARCHAR";
130 case sdbc::DataType::DECIMAL
:
131 aTypeName
= "DECIMAL";
133 case sdbc::DataType::BIT
:
136 case sdbc::DataType::DATE
:
139 case sdbc::DataType::TIME
:
142 case sdbc::DataType::TIMESTAMP
:
143 aTypeName
= "TIMESTAMP";
146 SAL_WARN("connectivity.writer", "missing type name");
150 // check if the column name already exists
151 OUString aAlias
= aColumnName
;
152 auto aFind
= connectivity::find(m_aColumns
->begin(), m_aColumns
->end(), aAlias
, aCase
);
153 sal_Int32 nExprCnt
= 0;
154 while (aFind
!= m_aColumns
->end())
156 aAlias
= aColumnName
+ OUString::number(++nExprCnt
);
157 aFind
= connectivity::find(m_aColumns
->begin(), m_aColumns
->end(), aAlias
, aCase
);
160 rtl::Reference
<sdbcx::OColumn
> pColumn
= new sdbcx::OColumn(
161 aAlias
, aTypeName
, OUString(), OUString(), sdbc::ColumnValue::NULLABLE
, nPrecision
,
162 nDecimals
, eType
, false, false, bCurrency
, bStoresMixedCaseQuotedIdentifiers
,
163 m_CatalogName
, getSchema(), getName());
164 m_aColumns
->push_back(pColumn
);
168 OWriterTable::OWriterTable(sdbcx::OCollection
* _pTables
, OWriterConnection
* _pConnection
,
169 const OUString
& Name
, const OUString
& Type
)
170 : OWriterTable_BASE(_pTables
, _pConnection
, Name
, Type
, OUString() /*Description*/,
171 OUString() /*SchemaName*/, OUString() /*CatalogName*/)
172 , m_pWriterConnection(_pConnection
)
176 void OWriterTable::construct()
178 uno::Reference
<text::XTextDocument
> xDoc
= m_pWriterConnection
->acquireDoc();
181 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(xDoc
, uno::UNO_QUERY
);
182 uno::Reference
<container::XNameAccess
> xTables
= xTextTablesSupplier
->getTextTables();
183 if (xTables
.is() && xTables
->hasByName(m_Name
))
185 m_xTable
.set(xTables
->getByName(m_Name
), uno::UNO_QUERY
);
188 lcl_GetDataArea(m_xTable
, m_nDataCols
, m_nDataRows
);
189 m_bHasHeaders
= true;
199 void SAL_CALL
OWriterTable::disposing()
201 OFileTable::disposing();
202 ::osl::MutexGuard
aGuard(m_aMutex
);
203 m_aColumns
= nullptr;
204 if (m_pWriterConnection
)
205 m_pWriterConnection
->releaseDoc();
206 m_pWriterConnection
= nullptr;
209 bool OWriterTable::fetchRow(OValueRefRow
& _rRow
, const OSQLColumns
& _rCols
, bool bRetrieveData
)
213 _rRow
->setDeleted(false);
214 *(*_rRow
)[0] = m_nFilePos
;
221 const OValueRefVector::size_type nCount
= std::min(_rRow
->size(), _rCols
.size() + 1);
222 for (OValueRefVector::size_type i
= 1; i
< nCount
; i
++)
224 if ((*_rRow
)[i
]->isBound())
226 lcl_SetValue((*_rRow
)[i
]->get(), m_xTable
, m_nStartCol
, m_bHasHeaders
, m_nFilePos
, i
);
234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */