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 <indexcollection.hxx>
21 #include <comphelper/diagnose_ex.hxx>
22 #include <com/sun/star/sdbc/SQLException.hpp>
23 #include <com/sun/star/sdbcx/XAppend.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
26 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
27 #include <comphelper/extract.hxx>
28 #include <com/sun/star/sdbcx/XDrop.hpp>
33 using namespace ::com::sun::star::uno
;
34 using namespace ::com::sun::star::container
;
35 using namespace ::com::sun::star::beans
;
36 using namespace ::com::sun::star::sdbcx
;
37 using namespace ::com::sun::star::sdbc
;
40 OIndexCollection::OIndexCollection()
44 OIndexCollection::OIndexCollection(const OIndexCollection
& _rSource
)
49 OIndexCollection
& OIndexCollection::operator=(const OIndexCollection
& _rSource
)
52 m_xIndexes
= _rSource
.m_xIndexes
;
53 m_aIndexes
= _rSource
.m_aIndexes
;
57 void OIndexCollection::attach(const Reference
< XNameAccess
>& _rxIndexes
)
59 implConstructFrom(_rxIndexes
);
62 void OIndexCollection::detach()
68 Indexes::const_iterator
OIndexCollection::find(const OUString
& _rName
) const
71 return std::find_if(m_aIndexes
.cbegin(), m_aIndexes
.cend(),
72 [&_rName
](const OIndex
& rIndex
) { return rIndex
.sName
== _rName
; });
75 Indexes::iterator
OIndexCollection::find(const OUString
& _rName
)
78 return std::find_if(m_aIndexes
.begin(), m_aIndexes
.end(),
79 [&_rName
](const OIndex
& rIndex
) { return rIndex
.sName
== _rName
; });
82 Indexes::const_iterator
OIndexCollection::findOriginal(const OUString
& _rName
) const
85 return std::find_if(m_aIndexes
.cbegin(), m_aIndexes
.cend(),
86 [&_rName
](const OIndex
& rIndex
) { return rIndex
.getOriginalName() == _rName
; });
89 Indexes::iterator
OIndexCollection::findOriginal(const OUString
& _rName
)
92 return std::find_if(m_aIndexes
.begin(), m_aIndexes
.end(),
93 [&_rName
](const OIndex
& rIndex
) { return rIndex
.getOriginalName() == _rName
; });
96 void OIndexCollection::commitNewIndex(const Indexes::iterator
& _rPos
)
98 OSL_ENSURE(_rPos
->isNew(), "OIndexCollection::commitNewIndex: index must be new!");
102 Reference
< XDataDescriptorFactory
> xIndexFactory(m_xIndexes
, UNO_QUERY
);
103 Reference
< XAppend
> xAppendIndex(xIndexFactory
, UNO_QUERY
);
104 if (!xAppendIndex
.is())
106 OSL_FAIL("OIndexCollection::commitNewIndex: missing an interface of the index container!");
110 Reference
< XPropertySet
> xIndexDescriptor
= xIndexFactory
->createDataDescriptor();
111 Reference
< XColumnsSupplier
> xColsSupp(xIndexDescriptor
, UNO_QUERY
);
112 Reference
< XNameAccess
> xCols
;
114 xCols
= xColsSupp
->getColumns();
116 Reference
< XDataDescriptorFactory
> xColumnFactory(xCols
, UNO_QUERY
);
117 Reference
< XAppend
> xAppendCols(xColumnFactory
, UNO_QUERY
);
118 if (!xAppendCols
.is())
120 OSL_FAIL("OIndexCollection::commitNewIndex: invalid index descriptor returned!");
124 // set the properties
125 static constexpr OUString s_sNamePropertyName
= u
"Name"_ustr
;
126 // the index' own props
127 xIndexDescriptor
->setPropertyValue(u
"IsUnique"_ustr
, css::uno::Any(_rPos
->bUnique
));
128 xIndexDescriptor
->setPropertyValue(s_sNamePropertyName
, Any(_rPos
->sName
));
131 for (auto const& field
: _rPos
->aFields
)
133 OSL_ENSURE(!xCols
->hasByName(field
.sFieldName
), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!");
135 Reference
< XPropertySet
> xColDescriptor
= xColumnFactory
->createDataDescriptor();
136 OSL_ENSURE(xColDescriptor
.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!");
137 if (xColDescriptor
.is())
139 xColDescriptor
->setPropertyValue(u
"IsAscending"_ustr
, css::uno::Any(field
.bSortAscending
));
140 xColDescriptor
->setPropertyValue(s_sNamePropertyName
, Any(field
.sFieldName
));
141 xAppendCols
->appendByDescriptor(xColDescriptor
);
145 xAppendIndex
->appendByDescriptor(xIndexDescriptor
);
147 _rPos
->flagAsCommitted(GrantIndexAccess());
148 _rPos
->clearModified();
154 catch( const Exception
& )
156 DBG_UNHANDLED_EXCEPTION("dbaccess");
160 bool OIndexCollection::dropNoRemove(const Indexes::iterator
& _rPos
)
164 OSL_ENSURE(m_xIndexes
->hasByName(_rPos
->getOriginalName()), "OIndexCollection::drop: invalid name!");
166 Reference
< XDrop
> xDropIndex(m_xIndexes
, UNO_QUERY
);
167 if (!xDropIndex
.is())
169 OSL_FAIL("OIndexCollection::drop: no XDrop interface!");
173 xDropIndex
->dropByName(_rPos
->getOriginalName());
179 catch( const Exception
& )
181 DBG_UNHANDLED_EXCEPTION("dbaccess");
185 // adjust the OIndex structure
186 Indexes::iterator aDropped
= findOriginal(_rPos
->getOriginalName());
187 OSL_ENSURE(aDropped
!= m_aIndexes
.end(), "OIndexCollection::drop: invalid original name, but successful commit?!");
188 aDropped
->flagAsNew(GrantIndexAccess());
193 bool OIndexCollection::drop(const Indexes::iterator
& _rPos
)
195 OSL_ENSURE((_rPos
>= m_aIndexes
.begin()) && (_rPos
< m_aIndexes
.end()),
196 "OIndexCollection::drop: invalid position (fasten your seatbelt... this will crash)!");
199 if (!dropNoRemove(_rPos
))
202 // adjust the index array
203 m_aIndexes
.erase(_rPos
);
207 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
)
209 // get the UNO descriptor for the index
210 Reference
< XPropertySet
> xIndex
;
211 m_xIndexes
->getByName(_rIndex
.getOriginalName()) >>= xIndex
;
214 OSL_FAIL("OIndexCollection::implFillIndexInfo: got an invalid index object!");
217 implFillIndexInfo(_rIndex
, xIndex
);
220 void OIndexCollection::implFillIndexInfo(OIndex
& _rIndex
, const Reference
< XPropertySet
>& _rxDescriptor
)
222 _rIndex
.bPrimaryKey
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(u
"IsPrimaryKeyIndex"_ustr
));
223 _rIndex
.bUnique
= ::cppu::any2bool(_rxDescriptor
->getPropertyValue(u
"IsUnique"_ustr
));
224 _rxDescriptor
->getPropertyValue(u
"Catalog"_ustr
) >>= _rIndex
.sDescription
;
227 Reference
< XColumnsSupplier
> xSuppCols(_rxDescriptor
, UNO_QUERY
);
228 Reference
< XNameAccess
> xCols
;
230 xCols
= xSuppCols
->getColumns();
231 OSL_ENSURE(xCols
.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!");
235 Sequence
< OUString
> aFieldNames
= xCols
->getElementNames();
236 _rIndex
.aFields
.clear();
237 _rIndex
.aFields
.reserve(aFieldNames
.getLength());
239 for (auto& fieldName
: aFieldNames
)
241 // extract the column
242 Reference
<XPropertySet
> xIndexColumn
;
243 xCols
->getByName(fieldName
) >>= xIndexColumn
;
244 if (!xIndexColumn
.is())
246 OSL_FAIL("OIndexCollection::implFillIndexInfo: invalid index column!");
250 // get the relevant properties
251 _rIndex
.aFields
.push_back({ .sFieldName
= fieldName
,
252 .bSortAscending
= cppu::any2bool(
253 xIndexColumn
->getPropertyValue(u
"IsAscending"_ustr
)) });
257 void OIndexCollection::resetIndex(const Indexes::iterator
& _rPos
)
259 OSL_ENSURE(_rPos
>= m_aIndexes
.begin() && _rPos
< m_aIndexes
.end(),
260 "OIndexCollection::resetIndex: invalid position!");
264 _rPos
->sName
= _rPos
->getOriginalName();
265 implFillIndexInfo(*_rPos
);
267 _rPos
->clearModified();
268 _rPos
->flagAsCommitted(GrantIndexAccess());
274 catch( const Exception
& )
276 DBG_UNHANDLED_EXCEPTION("dbaccess");
280 Indexes::iterator
OIndexCollection::insert(const OUString
& _rName
)
282 OSL_ENSURE(end() == find(_rName
), "OIndexCollection::insert: invalid new name!");
283 OIndex
aNewIndex((OUString())); // the empty string indicates the index is a new one
284 aNewIndex
.sName
= _rName
;
285 m_aIndexes
.push_back(aNewIndex
);
286 return m_aIndexes
.end() - 1; // the last element is the new one ...
289 void OIndexCollection::implConstructFrom(const Reference
< XNameAccess
>& _rxIndexes
)
293 m_xIndexes
= _rxIndexes
;
294 if (!m_xIndexes
.is())
297 // loop through all the indexes
298 for (auto& name
: m_xIndexes
->getElementNames())
300 // extract the index object
301 Reference
< XPropertySet
> xIndex
;
302 m_xIndexes
->getByName(name
) >>= xIndex
;
305 OSL_FAIL("OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!");
309 // fill the OIndex structure
310 OIndex
aCurrentIndex(name
);
311 implFillIndexInfo(aCurrentIndex
, xIndex
);
312 m_aIndexes
.push_back(aCurrentIndex
);
318 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */