Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / firebird / Table.cxx
blob086ecd465e26ba81cfe56424becf14e007e8cd41
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "Columns.hxx"
11 #include "Indexes.hxx"
12 #include "Keys.hxx"
13 #include "Table.hxx"
15 #include <TConnection.hxx>
17 #include <comphelper/sequence.hxx>
18 #include <connectivity/dbtools.hxx>
20 #include <com/sun/star/sdbc/ColumnValue.hpp>
21 #include <com/sun/star/sdbcx/Privilege.hpp>
23 using namespace ::connectivity;
24 using namespace ::connectivity::firebird;
25 using namespace ::connectivity::sdbcx;
27 using namespace ::osl;
28 using namespace ::rtl;
30 using namespace ::com::sun::star;
31 using namespace ::com::sun::star::beans;
32 using namespace ::com::sun::star::container;
33 using namespace ::com::sun::star::sdbc;
34 using namespace ::com::sun::star::sdbcx;
35 using namespace ::com::sun::star::uno;
37 Table::Table(Tables* pTables,
38 Mutex& rMutex,
39 const uno::Reference< XConnection >& rConnection):
40 OTableHelper(pTables,
41 rConnection,
42 true),
43 m_rMutex(rMutex),
44 m_nPrivileges(0)
46 construct();
49 Table::Table(Tables* pTables,
50 Mutex& rMutex,
51 const uno::Reference< XConnection >& rConnection,
52 const OUString& rName,
53 const OUString& rType,
54 const OUString& rDescription):
55 OTableHelper(pTables,
56 rConnection,
57 true,
58 rName,
59 rType,
60 rDescription,
61 "",
62 ""),
63 m_rMutex(rMutex),
64 m_nPrivileges(0)
66 construct();
69 void Table::construct()
71 OTableHelper::construct();
72 if (!isNew())
74 // TODO: get privileges when in non-embedded mode.
75 m_nPrivileges = Privilege::DROP |
76 Privilege::REFERENCE |
77 Privilege::ALTER |
78 Privilege::CREATE |
79 Privilege::READ |
80 Privilege::DELETE |
81 Privilege::UPDATE |
82 Privilege::INSERT |
83 Privilege::SELECT;
84 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES),
85 PROPERTY_ID_PRIVILEGES,
86 PropertyAttribute::READONLY,
87 &m_nPrivileges,
88 ::getCppuType(&m_nPrivileges));
91 //----- OTableHelper ---------------------------------------------------------
92 OCollection* Table::createColumns(const TStringVector& rNames)
94 return new Columns(*this,
95 m_rMutex,
96 rNames);
99 OCollection* Table::createKeys(const TStringVector& rNames)
101 return new Keys(this,
102 m_rMutex,
103 rNames);
106 OCollection* Table::createIndexes(const TStringVector& rNames)
108 return new Indexes(this,
109 m_rMutex,
110 rNames);
113 //----- XAlterTable -----------------------------------------------------------
114 void SAL_CALL Table::alterColumnByName(const OUString& rColName,
115 const uno::Reference< XPropertySet >& rDescriptor)
116 throw(SQLException, NoSuchElementException, RuntimeException, std::exception)
118 MutexGuard aGuard(m_rMutex);
119 checkDisposed(WeakComponentImplHelperBase::rBHelper.bDisposed);
121 uno::Reference< XPropertySet > xColumn(m_pColumns->getByName(rColName), UNO_QUERY);
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 // TODO: remainder -- these are all "optional" so have to detect presence and change.
134 bool bDefaultChanged = xColumn->getPropertyValue("DefaultValue")
135 != rDescriptor->getPropertyValue("DefaultValue");
137 // TODO: quote identifiers as needed.
138 if (bNameChanged)
140 OUString sNewTableName;
141 rDescriptor->getPropertyValue("Name") >>= sNewTableName;
142 OUString sSql(getAlterTableColumn(rColName)
143 + " TO \"" + sNewTableName + "\"");
145 getConnection()->createStatement()->execute(sSql);
148 if (bTypeChanged || bTypeNameChanged || bPrecisionChanged || bScaleChanged)
150 // If bPrecisionChanged this will only succeed if we have increased the
151 // precision, otherwise an exception is thrown -- however the base
152 // gui then offers to delete and recreate the column.
153 OUString sSql(getAlterTableColumn(rColName) + "TYPE " +
154 ::dbtools::createStandardTypePart(rDescriptor, getConnection()));
155 getConnection()->createStatement()->execute(sSql);
156 // TODO: could cause errors e.g. if incompatible types, deal with them here as appropriate.
157 // possibly we have to wrap things in Util::evaluateStatusVector.
160 if (bIsNullableChanged)
162 sal_Int32 nNullabble = 0;
163 rDescriptor->getPropertyValue("IsNullable") >>= nNullabble;
165 if (nNullabble != ColumnValue::NULLABLE_UNKNOWN)
168 OUString sSql;
169 // Dirty hack: can't change null directly in sql, we have to fiddle
170 // the system tables manually.
171 if (nNullabble == ColumnValue::NULLABLE)
173 sSql = "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "
174 "WHERE RDB$FIELD_NAME = '" + rColName + "' "
175 "AND RDB$RELATION_NAME = '" + getName() + "'";
177 else if (nNullabble == ColumnValue::NO_NULLS)
179 // And if we are making NOT NULL then we have to make sure we have
180 // no nulls left in the column.
181 OUString sFillNulls("UPDATE \"" + getName() + "\" SET \""
182 + rColName + "\" = 0 "
183 "WHERE \"" + rColName + "\" IS NULL");
184 getConnection()->createStatement()->execute(sFillNulls);
186 sSql = "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "
187 "WHERE RDB$FIELD_NAME = '" + rColName + "' "
188 "AND RDB$RELATION_NAME = '" + getName() + "'";
190 getConnection()->createStatement()->execute(sSql);
192 else
194 SAL_WARN("connectivity.firebird", "Attempting to set Nullable to NULLABLE_UNKNOWN");
198 if (bIsAutoIncrementChanged)
200 // TODO: changeType
203 if (bDefaultChanged)
205 OUString sOldDefault, sNewDefault;
206 xColumn->getPropertyValue("DefaultValue") >>= sOldDefault;
207 rDescriptor->getPropertyValue("DefaultValue") >>= sNewDefault;
209 OUString sSql;
210 if (sNewDefault.isEmpty())
211 sSql = getAlterTableColumn(rColName) + "DROP DEFAULT";
212 else
213 sSql = getAlterTableColumn(rColName) + "SET DEFAULT " + sNewDefault;
215 getConnection()->createStatement()->execute(sSql);
218 m_pColumns->refresh();
221 // ----- XRename --------------------------------------------------------------
222 void SAL_CALL Table::rename(const OUString& rName)
223 throw(SQLException, ElementExistException, RuntimeException, std::exception)
225 (void) rName;
226 throw RuntimeException(); // Firebird doesn't support this.
229 // ----- XInterface -----------------------------------------------------------
230 Any SAL_CALL Table::queryInterface(const Type& rType)
231 throw(RuntimeException, std::exception)
233 if (rType.getTypeName() == "com.sun.star.sdbcx.XRename")
234 return Any();
236 return OTableHelper::queryInterface(rType);
239 // ----- XTypeProvider --------------------------------------------------------
240 uno::Sequence< Type > SAL_CALL Table::getTypes()
241 throw(RuntimeException, std::exception)
243 uno::Sequence< Type > aTypes = OTableHelper::getTypes();
245 for (int i = 0; i < aTypes.getLength(); i++)
247 if (aTypes[i].getTypeName() == "com.sun.star.sdbcx.XRename")
249 ::comphelper::removeElementAt(aTypes, i);
250 break;
254 return OTableHelper::getTypes();
257 OUString Table::getAlterTableColumn(const OUString& rColumn)
259 return ("ALTER TABLE \"" + getName() + "\" ALTER COLUMN \"" + rColumn + "\" ");
262 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */