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
;
29 using namespace ::com::sun::star
;
30 using namespace ::com::sun::star::beans
;
31 using namespace ::com::sun::star::container
;
32 using namespace ::com::sun::star::sdbc
;
33 using namespace ::com::sun::star::sdbcx
;
34 using namespace ::com::sun::star::uno
;
36 Table::Table(Tables
* pTables
,
38 const uno::Reference
< XConnection
>& rConnection
):
48 Table::Table(Tables
* pTables
,
50 const uno::Reference
< XConnection
>& rConnection
,
51 const OUString
& rName
,
52 const OUString
& rType
,
53 const OUString
& rDescription
):
68 void Table::construct()
70 OTableHelper::construct();
73 // TODO: get privileges when in non-embedded mode.
74 m_nPrivileges
= Privilege::DROP
|
75 Privilege::REFERENCE
|
83 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
),
84 PROPERTY_ID_PRIVILEGES
,
85 PropertyAttribute::READONLY
,
87 cppu::UnoType
<decltype(m_nPrivileges
)>::get());
90 //----- OTableHelper ---------------------------------------------------------
91 OCollection
* Table::createColumns(const TStringVector
& rNames
)
93 return new Columns(*this,
98 OCollection
* Table::createKeys(const TStringVector
& rNames
)
100 return new Keys(this,
105 OCollection
* Table::createIndexes(const TStringVector
& rNames
)
107 return new Indexes(this,
112 //----- XAlterTable -----------------------------------------------------------
113 void SAL_CALL
Table::alterColumnByName(const OUString
& rColName
,
114 const uno::Reference
< XPropertySet
>& rDescriptor
)
115 throw(SQLException
, NoSuchElementException
, RuntimeException
, std::exception
)
117 MutexGuard
aGuard(m_rMutex
);
118 checkDisposed(WeakComponentImplHelperBase::rBHelper
.bDisposed
);
120 uno::Reference
< XPropertySet
> xColumn(m_pColumns
->getByName(rColName
), UNO_QUERY
);
123 const bool bNameChanged
= xColumn
->getPropertyValue("Name") != rDescriptor
->getPropertyValue("Name");
124 // sdbcx::ColumnDescriptor
125 const bool bTypeChanged
= xColumn
->getPropertyValue("Type") != rDescriptor
->getPropertyValue("Type");
126 const bool bTypeNameChanged
= xColumn
->getPropertyValue("TypeName") != rDescriptor
->getPropertyValue("TypeName");
127 const bool bPrecisionChanged
= xColumn
->getPropertyValue("Precision") != rDescriptor
->getPropertyValue("Precision");
128 const bool bScaleChanged
= xColumn
->getPropertyValue("Scale") != rDescriptor
->getPropertyValue("Scale");
129 const bool bIsNullableChanged
= xColumn
->getPropertyValue("IsNullable") != rDescriptor
->getPropertyValue("IsNullable");
130 const bool bIsAutoIncrementChanged
= xColumn
->getPropertyValue("IsAutoIncrement") != rDescriptor
->getPropertyValue("IsAutoIncrement");
131 // TODO: remainder -- these are all "optional" so have to detect presence and change.
133 bool bDefaultChanged
= xColumn
->getPropertyValue("DefaultValue")
134 != rDescriptor
->getPropertyValue("DefaultValue");
136 // TODO: quote identifiers as needed.
139 OUString sNewTableName
;
140 rDescriptor
->getPropertyValue("Name") >>= sNewTableName
;
141 OUString
sSql(getAlterTableColumn(rColName
)
142 + " TO \"" + sNewTableName
+ "\"");
144 getConnection()->createStatement()->execute(sSql
);
147 if (bTypeChanged
|| bTypeNameChanged
|| bPrecisionChanged
|| bScaleChanged
)
149 // If bPrecisionChanged this will only succeed if we have increased the
150 // precision, otherwise an exception is thrown -- however the base
151 // gui then offers to delete and recreate the column.
152 OUString
sSql(getAlterTableColumn(rColName
) + "TYPE " +
153 ::dbtools::createStandardTypePart(rDescriptor
, getConnection()));
154 getConnection()->createStatement()->execute(sSql
);
155 // TODO: could cause errors e.g. if incompatible types, deal with them here as appropriate.
156 // possibly we have to wrap things in Util::evaluateStatusVector.
159 if (bIsNullableChanged
)
161 sal_Int32 nNullabble
= 0;
162 rDescriptor
->getPropertyValue("IsNullable") >>= nNullabble
;
164 if (nNullabble
!= ColumnValue::NULLABLE_UNKNOWN
)
168 // Dirty hack: can't change null directly in sql, we have to fiddle
169 // the system tables manually.
170 if (nNullabble
== ColumnValue::NULLABLE
)
172 sSql
= "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "
173 "WHERE RDB$FIELD_NAME = '" + rColName
+ "' "
174 "AND RDB$RELATION_NAME = '" + getName() + "'";
176 else if (nNullabble
== ColumnValue::NO_NULLS
)
178 // And if we are making NOT NULL then we have to make sure we have
179 // no nulls left in the column.
180 OUString
sFillNulls("UPDATE \"" + getName() + "\" SET \""
181 + rColName
+ "\" = 0 "
182 "WHERE \"" + rColName
+ "\" IS NULL");
183 getConnection()->createStatement()->execute(sFillNulls
);
185 sSql
= "UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "
186 "WHERE RDB$FIELD_NAME = '" + rColName
+ "' "
187 "AND RDB$RELATION_NAME = '" + getName() + "'";
189 getConnection()->createStatement()->execute(sSql
);
193 SAL_WARN("connectivity.firebird", "Attempting to set Nullable to NULLABLE_UNKNOWN");
197 if (bIsAutoIncrementChanged
)
204 OUString sOldDefault
, sNewDefault
;
205 xColumn
->getPropertyValue("DefaultValue") >>= sOldDefault
;
206 rDescriptor
->getPropertyValue("DefaultValue") >>= sNewDefault
;
209 if (sNewDefault
.isEmpty())
210 sSql
= getAlterTableColumn(rColName
) + "DROP DEFAULT";
212 sSql
= getAlterTableColumn(rColName
) + "SET DEFAULT " + sNewDefault
;
214 getConnection()->createStatement()->execute(sSql
);
217 m_pColumns
->refresh();
220 // ----- XRename --------------------------------------------------------------
221 void SAL_CALL
Table::rename(const OUString
& rName
)
222 throw(SQLException
, ElementExistException
, RuntimeException
, std::exception
)
225 throw RuntimeException(); // Firebird doesn't support this.
228 // ----- XInterface -----------------------------------------------------------
229 Any SAL_CALL
Table::queryInterface(const Type
& rType
)
230 throw(RuntimeException
, std::exception
)
232 if (rType
.getTypeName() == "com.sun.star.sdbcx.XRename")
235 return OTableHelper::queryInterface(rType
);
238 // ----- XTypeProvider --------------------------------------------------------
239 uno::Sequence
< Type
> SAL_CALL
Table::getTypes()
240 throw(RuntimeException
, std::exception
)
242 uno::Sequence
< Type
> aTypes
= OTableHelper::getTypes();
244 for (int i
= 0; i
< aTypes
.getLength(); i
++)
246 if (aTypes
[i
].getTypeName() == "com.sun.star.sdbcx.XRename")
248 ::comphelper::removeElementAt(aTypes
, i
);
253 return OTableHelper::getTypes();
256 OUString
Table::getAlterTableColumn(const OUString
& rColumn
)
258 return ("ALTER TABLE \"" + getName() + "\" ALTER COLUMN \"" + rColumn
+ "\" ");
261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */