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/.
10 #include "Columns.hxx"
11 #include "Indexes.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
,
39 const uno::Reference
< XConnection
>& rConnection
):
49 Table::Table(Tables
* pTables
,
51 const uno::Reference
< XConnection
>& rConnection
,
52 const OUString
& rName
,
53 const OUString
& rType
,
54 const OUString
& rDescription
):
69 void Table::construct()
71 OTableHelper::construct();
74 // TODO: get privileges when in non-embedded mode.
75 m_nPrivileges
= Privilege::DROP
|
76 Privilege::REFERENCE
|
84 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
),
85 PROPERTY_ID_PRIVILEGES
,
86 PropertyAttribute::READONLY
,
88 ::getCppuType(&m_nPrivileges
));
91 //----- OTableHelper ---------------------------------------------------------
92 OCollection
* Table::createColumns(const TStringVector
& rNames
)
94 return new Columns(*this,
99 OCollection
* Table::createKeys(const TStringVector
& rNames
)
101 return new Keys(this,
106 OCollection
* Table::createIndexes(const TStringVector
& rNames
)
108 return new Indexes(this,
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
);
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.
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
)
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
);
194 SAL_WARN("connectivity.firebird", "Attempting to set Nullable to NULLABLE_UNKNOWN");
198 if (bIsAutoIncrementChanged
)
205 OUString sOldDefault
, sNewDefault
;
206 xColumn
->getPropertyValue("DefaultValue") >>= sOldDefault
;
207 rDescriptor
->getPropertyValue("DefaultValue") >>= sNewDefault
;
210 if (sNewDefault
.isEmpty())
211 sSql
= getAlterTableColumn(rColName
) + "DROP DEFAULT";
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
)
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")
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
);
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: */