LibreOffice Module connectivity (master) 1
Table.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10#include "Columns.hxx"
11#include "Indexes.hxx"
12#include "Keys.hxx"
13#include "Table.hxx"
14
15#include <TConnection.hxx>
16
17#include <sal/log.hxx>
20
21#include <com/sun/star/sdbc/ColumnValue.hpp>
22#include <com/sun/star/sdbcx/Privilege.hpp>
23#include <com/sun/star/beans/PropertyAttribute.hpp>
24
25using namespace ::connectivity;
26using namespace ::connectivity::firebird;
27using namespace ::connectivity::sdbcx;
28
29using namespace ::osl;
30
31using namespace ::com::sun::star;
32using namespace ::com::sun::star::beans;
33using namespace ::com::sun::star::container;
34using namespace ::com::sun::star::sdbc;
35using namespace ::com::sun::star::sdbcx;
36using namespace ::com::sun::star::uno;
37
38Table::Table(Tables* pTables,
39 Mutex& rMutex,
40 const uno::Reference< XConnection >& rConnection):
41 OTableHelper(pTables,
42 rConnection,
43 true),
44 m_rMutex(rMutex),
45 m_nPrivileges(0)
46{
47 construct();
48}
49
50Table::Table(Tables* pTables,
51 Mutex& rMutex,
52 const uno::Reference< XConnection >& rConnection,
53 const OUString& rName,
54 const OUString& rType,
55 const OUString& rDescription):
56 OTableHelper(pTables,
57 rConnection,
58 true,
59 rName,
60 rType,
61 rDescription,
62 "",
63 ""),
64 m_rMutex(rMutex),
65 m_nPrivileges(0)
66{
67 construct();
68}
69
70void Table::construct()
71{
72 OTableHelper::construct();
73 if (isNew())
74 return;
75
76 // TODO: get privileges when in non-embedded mode.
77 m_nPrivileges = Privilege::DROP |
78 Privilege::REFERENCE |
79 Privilege::ALTER |
80 Privilege::CREATE |
81 Privilege::READ |
82 Privilege::DELETE |
83 Privilege::UPDATE |
84 Privilege::INSERT |
85 Privilege::SELECT;
86 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES),
88 PropertyAttribute::READONLY,
89 &m_nPrivileges,
90 cppu::UnoType<decltype(m_nPrivileges)>::get());
91}
92//----- OTableHelper ---------------------------------------------------------
93OCollection* Table::createColumns(const ::std::vector< OUString>& rNames)
94{
95 return new Columns(*this,
96 m_rMutex,
97 rNames);
98}
99
100OCollection* Table::createKeys(const ::std::vector< OUString>& rNames)
101{
102 return new Keys(this,
103 m_rMutex,
104 rNames);
105}
106
107OCollection* Table::createIndexes(const ::std::vector< OUString>& rNames)
108{
109 return new Indexes(this,
110 m_rMutex,
111 rNames);
112}
113
114//----- XAlterTable -----------------------------------------------------------
115void SAL_CALL Table::alterColumnByName(const OUString& rColName,
116 const uno::Reference< XPropertySet >& rDescriptor)
117{
118 MutexGuard aGuard(m_rMutex);
119 checkDisposed(WeakComponentImplHelperBase::rBHelper.bDisposed);
120
121 uno::Reference< XPropertySet > xColumn(m_xColumns->getByName(rColName), UNO_QUERY);
122
123 // sdbcx::Descriptor
124 const bool bNameChanged = xColumn->getPropertyValue("Name") != rDescriptor->getPropertyValue("Name");
125 // sdbcx::ColumnDescriptor
126 const bool bTypeChanged = xColumn->getPropertyValue("Type") != rDescriptor->getPropertyValue("Type");
127 const bool bTypeNameChanged = xColumn->getPropertyValue("TypeName") != rDescriptor->getPropertyValue("TypeName");
128 const bool bPrecisionChanged = xColumn->getPropertyValue("Precision") != rDescriptor->getPropertyValue("Precision");
129 const bool bScaleChanged = xColumn->getPropertyValue("Scale") != rDescriptor->getPropertyValue("Scale");
130 const bool bIsNullableChanged = xColumn->getPropertyValue("IsNullable") != rDescriptor->getPropertyValue("IsNullable");
131 const bool bIsAutoIncrementChanged = xColumn->getPropertyValue("IsAutoIncrement") != rDescriptor->getPropertyValue("IsAutoIncrement");
132
133 // TODO: remainder -- these are all "optional" so have to detect presence and change.
134
135 bool bDefaultChanged = xColumn->getPropertyValue("DefaultValue")
136 != rDescriptor->getPropertyValue("DefaultValue");
137
138 if (bTypeChanged || bTypeNameChanged || bPrecisionChanged || bScaleChanged)
139 {
140 // If bPrecisionChanged this will only succeed if we have increased the
141 // precision, otherwise an exception is thrown -- however the base
142 // gui then offers to delete and recreate the column.
143 OUString sSql(getAlterTableColumn(rColName) + "TYPE " +
145 getConnection()->createStatement()->execute(sSql);
146 // TODO: could cause errors e.g. if incompatible types, deal with them here as appropriate.
147 // possibly we have to wrap things in Util::evaluateStatusVector.
148 }
149
150 if (bIsNullableChanged)
151 {
152 sal_Int32 nNullable = 0;
153 rDescriptor->getPropertyValue("IsNullable") >>= nNullable;
154
155 if (nNullable != ColumnValue::NULLABLE_UNKNOWN)
156 {
157
158 OUString sSql;
159 // Dirty hack: can't change null directly in sql, we have to fiddle
160 // the system tables manually.
161 if (nNullable == ColumnValue::NULLABLE)
162 {
163 sSql = "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "
164 "WHERE RDB$FIELD_NAME = '" + rColName + "' "
165 "AND RDB$RELATION_NAME = '" + getName() + "'";
166 }
167 else if (nNullable == ColumnValue::NO_NULLS)
168 {
169 // And if we are making NOT NULL then we have to make sure we have
170 // no nulls left in the column.
171 OUString sFillNulls("UPDATE \"" + getName() + "\" SET \""
172 + rColName + "\" = 0 "
173 "WHERE \"" + rColName + "\" IS NULL");
174 getConnection()->createStatement()->execute(sFillNulls);
175
176 sSql = "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "
177 "WHERE RDB$FIELD_NAME = '" + rColName + "' "
178 "AND RDB$RELATION_NAME = '" + getName() + "'";
179 }
180 getConnection()->createStatement()->execute(sSql);
181 }
182 else
183 {
184 SAL_WARN("connectivity.firebird", "Attempting to set Nullable to NULLABLE_UNKNOWN");
185 }
186 }
187
188 if (bIsAutoIncrementChanged)
189 {
191 "Changing autoincrement property of existing column is not supported",
192 ::dbtools::StandardSQLState::FUNCTION_NOT_SUPPORTED,
193 *this);
194
195 }
196
197 if (bDefaultChanged)
198 {
199 OUString sNewDefault;
200 rDescriptor->getPropertyValue("DefaultValue") >>= sNewDefault;
201
202 OUString sSql;
203 if (sNewDefault.isEmpty())
204 sSql = getAlterTableColumn(rColName) + "DROP DEFAULT";
205 else
206 sSql = getAlterTableColumn(rColName) + "SET DEFAULT " + sNewDefault;
207
208 getConnection()->createStatement()->execute(sSql);
209 }
210 // TODO: quote identifiers as needed.
211 if (bNameChanged)
212 {
213 OUString sNewColName;
214 rDescriptor->getPropertyValue("Name") >>= sNewColName;
215 OUString sSql(getAlterTableColumn(rColName)
216 + " TO \"" + sNewColName + "\"");
217
218 getConnection()->createStatement()->execute(sSql);
219 }
220
221
222 m_xColumns->refresh();
223}
224
225// ----- XRename --------------------------------------------------------------
226void SAL_CALL Table::rename(const OUString&)
227{
228 throw RuntimeException("Table renaming not supported by Firebird.");
229}
230
231// ----- XInterface -----------------------------------------------------------
232Any SAL_CALL Table::queryInterface(const Type& rType)
233{
234 if (rType.getTypeName() == "com.sun.star.sdbcx.XRename")
235 return Any();
236
237 return OTableHelper::queryInterface(rType);
238}
239
240OUString Table::getAlterTableColumn(std::u16string_view rColumn)
241{
242 return ("ALTER TABLE \"" + getName() + "\" ALTER COLUMN \"" + rColumn + "\" ");
243}
244
245/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
::osl::Mutex & m_rMutex
Reference< XColumn > xColumn
sal_Int32 nNullable
#define SAL_WARN(area, stream)
Type
void checkDisposed(bool _bThrow)
Definition: dbtools.cxx:1951
std::vector< OIndex > Indexes
OUString createStandardTypePart(const Reference< XPropertySet > &xColProp, const Reference< XConnection > &_xConnection, std::u16string_view _sCreatePattern)
Definition: dbtools2.cxx:67
Reference< XConnection > getConnection(const Reference< XRowSet > &_rxRowSet)
Definition: dbtools.cxx:348
void throwSQLException(const OUString &_rMessage, const OUString &_rSQLState, const Reference< XInterface > &_rxContext, const sal_Int32 _nErrorCode)
#define PROPERTY_ID_PRIVILEGES
Definition: propertyids.hxx:94