1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 
31 #include "connectivity/PColumn.hxx"
32 #include "connectivity/dbtools.hxx"
33 #include "TConnection.hxx"
34 
35 #include <comphelper/types.hxx>
36 #include <tools/diagnose_ex.h>
37 
38 using namespace ::comphelper;
39 using namespace connectivity;
40 using namespace dbtools;
41 using namespace connectivity::parse;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::sdbc;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::container;
46 
47 // -------------------------------------------------------------------------
48 OParseColumn::OParseColumn(const Reference<XPropertySet>& _xColumn,sal_Bool		_bCase)
49 	: connectivity::sdbcx::OColumn(	getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)))
50 								,	getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))
51 								,	getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))
52                                 ,	getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION)))
53 								,	getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))
54 								,	getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))
55 								,	getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))
56 								,	getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))
57 								,	getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)))
58 								,	sal_False
59 								,	getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))
60 								,	_bCase
61 								)
62 	, m_bFunction(sal_False)
63 	, m_bDbasePrecisionChanged(sal_False)
64 	, m_bAggregateFunction(sal_False)
65     , m_bIsSearchable( sal_True )
66 {
67 	construct();
68 }
69 
70 // -------------------------------------------------------------------------
71 OParseColumn::OParseColumn(	const ::rtl::OUString& _Name,
72 					const ::rtl::OUString& _TypeName,
73 					const ::rtl::OUString& _DefaultValue,
74                     const ::rtl::OUString& _Description,
75 					sal_Int32		_IsNullable,
76 					sal_Int32		_Precision,
77 					sal_Int32		_Scale,
78 					sal_Int32		_Type,
79 					sal_Bool		_IsAutoIncrement,
80 					sal_Bool		_IsCurrency,
81 					sal_Bool		_bCase
82 				) : connectivity::sdbcx::OColumn(_Name,
83 								  _TypeName,
84 								  _DefaultValue,
85                                   _Description,
86 								  _IsNullable,
87 								  _Precision,
88 								  _Scale,
89 								  _Type,
90 								  _IsAutoIncrement,
91 								  sal_False,
92 								  _IsCurrency,
93 								  _bCase)
94 	, m_bFunction(sal_False)
95 	, m_bDbasePrecisionChanged(sal_False)
96 	, m_bAggregateFunction(sal_False)
97     , m_bIsSearchable( sal_True )
98 {
99 	construct();
100 }
101 
102 // -------------------------------------------------------------------------
103 ::vos::ORef< OSQLColumns > OParseColumn::createColumnsForResultSet( const Reference< XResultSetMetaData >& _rxResMetaData,
104     const Reference< XDatabaseMetaData >& _rxDBMetaData,const Reference< XNameAccess>& i_xQueryColumns )
105 {
106     sal_Int32 nColumnCount = _rxResMetaData->getColumnCount();
107     ::vos::ORef< OSQLColumns > aReturn( new OSQLColumns ); aReturn->get().reserve( nColumnCount );
108 
109 	StringMap aColumnMap;
110     for ( sal_Int32 i = 1; i <= nColumnCount; ++i )
111     {
112         OParseColumn* pColumn = createColumnForResultSet( _rxResMetaData, _rxDBMetaData, i,aColumnMap );
113         aReturn->get().push_back( pColumn );
114         if ( i_xQueryColumns.is() && i_xQueryColumns->hasByName(pColumn->getRealName()) )
115         {
116             Reference<XPropertySet> xColumn(i_xQueryColumns->getByName(pColumn->getRealName()),UNO_QUERY_THROW);
117             ::rtl::OUString sLabel;
118             xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_LABEL)) >>= sLabel;
119             if ( sLabel.getLength() )
120                 pColumn->setLabel(sLabel);
121         }
122     }
123 
124     return aReturn;
125 }
126 
127 // -------------------------------------------------------------------------
128 OParseColumn* OParseColumn::createColumnForResultSet( const Reference< XResultSetMetaData >& _rxResMetaData,
129     const Reference< XDatabaseMetaData >& _rxDBMetaData, sal_Int32 _nColumnPos,StringMap& _rColumns )
130 {
131     ::rtl::OUString sLabel = _rxResMetaData->getColumnLabel( _nColumnPos );
132     // retrieve the name of the column
133 	// check for duplicate entries
134 	if(_rColumns.find(sLabel) != _rColumns.end())
135 	{
136 		::rtl::OUString sAlias(sLabel);
137 		sal_Int32 searchIndex=1;
138 		while(_rColumns.find(sAlias) != _rColumns.end())
139 		{
140             (sAlias = sLabel) += ::rtl::OUString::valueOf(searchIndex++);
141 		}
142 		sLabel = sAlias;
143 	}
144     _rColumns.insert(StringMap::value_type(sLabel,0));
145 	OParseColumn* pColumn = new OParseColumn(
146         sLabel,
147 		_rxResMetaData->getColumnTypeName( _nColumnPos ),
148         ::rtl::OUString(),
149         ::rtl::OUString(),
150         _rxResMetaData->isNullable( _nColumnPos ),
151         _rxResMetaData->getPrecision( _nColumnPos ),
152         _rxResMetaData->getScale( _nColumnPos ),
153         _rxResMetaData->getColumnType( _nColumnPos ),
154         _rxResMetaData->isAutoIncrement( _nColumnPos ),
155         _rxResMetaData->isCurrency( _nColumnPos ),
156         _rxDBMetaData->supportsMixedCaseQuotedIdentifiers()
157     );
158     const ::rtl::OUString sTableName = _rxResMetaData->getTableName( _nColumnPos );
159     if ( sTableName.getLength() )
160         pColumn->setTableName(  ::dbtools::composeTableName( _rxDBMetaData,
161             _rxResMetaData->getCatalogName( _nColumnPos ),
162             _rxResMetaData->getSchemaName( _nColumnPos ),
163             sTableName,
164             sal_False,
165             eComplete
166         ) );
167     pColumn->setIsSearchable( _rxResMetaData->isSearchable( _nColumnPos ) );
168     pColumn->setRealName(_rxResMetaData->getColumnName( _nColumnPos ));
169     pColumn->setLabel(sLabel);
170     return pColumn;
171 }
172 
173 // -------------------------------------------------------------------------
174 OParseColumn::~OParseColumn()
175 {
176 }
177 // -------------------------------------------------------------------------
178 void OParseColumn::construct()
179 {
180 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FUNCTION),				PROPERTY_ID_FUNCTION,				0,  &m_bFunction,		        ::getCppuType(reinterpret_cast< sal_Bool*>(NULL)));
181 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_AGGREGATEFUNCTION),		PROPERTY_ID_AGGREGATEFUNCTION,		0,  &m_bAggregateFunction,		::getCppuType(reinterpret_cast< sal_Bool*>(NULL)));
182 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TABLENAME),				PROPERTY_ID_TABLENAME,				0,  &m_aTableName,		        ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
183 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME),				PROPERTY_ID_REALNAME,				0,  &m_aRealName,		        ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
184 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DBASEPRECISIONCHANGED),	PROPERTY_ID_DBASEPRECISIONCHANGED,	0,  &m_bDbasePrecisionChanged,	::getCppuType(reinterpret_cast<sal_Bool*>(NULL)));
185     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISSEARCHABLE),	        PROPERTY_ID_ISSEARCHABLE,			0,  &m_bIsSearchable,           ::getCppuType(reinterpret_cast< sal_Bool*>(NULL)));
186     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_LABEL),				    PROPERTY_ID_LABEL,				    0,  &m_sLabel,		            ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
187 }
188 // -----------------------------------------------------------------------------
189 ::cppu::IPropertyArrayHelper* OParseColumn::createArrayHelper() const
190 {
191     return doCreateArrayHelper();
192 }
193 // -----------------------------------------------------------------------------
194 ::cppu::IPropertyArrayHelper & SAL_CALL OParseColumn::getInfoHelper()
195 {
196     OSL_ENSURE( !isNew(), "OParseColumn::getInfoHelper: a *new* ParseColumn?" );
197 	return *OParseColumn_PROP::getArrayHelper();
198 }
199 
200 // -----------------------------------------------------------------------------
201 namespace
202 {
203     ::rtl::OUString lcl_getColumnTableName( const Reference< XPropertySet >& i_parseColumn )
204     {
205         ::rtl::OUString sColumnTableName;
206         try
207         {
208             OSL_VERIFY( i_parseColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sColumnTableName );
209         }
210         catch( const Exception& )
211         {
212         	DBG_UNHANDLED_EXCEPTION();
213         }
214         return sColumnTableName;
215     }
216 }
217 
218 // -----------------------------------------------------------------------------
219 OOrderColumn::OOrderColumn(	const Reference<XPropertySet>& _xColumn, const ::rtl::OUString& i_rOriginatingTableName,
220                             sal_Bool	_bCase, sal_Bool _bAscending )
221 	: connectivity::sdbcx::OColumn(
222         getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),
223 		getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))),
224 		getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))),
225         getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION))),
226 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))),
227 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))),
228 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))),
229 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))),
230 		getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))),
231 		sal_False,
232 		getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY))),
233 		_bCase
234     )
235 	,m_bAscending(_bAscending)
236     ,m_sTableName( i_rOriginatingTableName )
237 {
238 	construct();
239 }
240 
241 // -----------------------------------------------------------------------------
242 OOrderColumn::OOrderColumn(	const Reference<XPropertySet>& _xColumn, sal_Bool _bCase, sal_Bool _bAscending )
243 	: connectivity::sdbcx::OColumn(
244         getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),
245 		getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))),
246 		getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))),
247         getString(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION))),
248 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))),
249 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))),
250 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))),
251 		getINT32(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))),
252 		getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))),
253 		sal_False,
254 		getBOOL(_xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY))),
255 		_bCase
256     )
257 	,m_bAscending(_bAscending)
258     ,m_sTableName( lcl_getColumnTableName( _xColumn ) )
259 {
260 	construct();
261 }
262 
263 // -------------------------------------------------------------------------
264 OOrderColumn::~OOrderColumn()
265 {
266 }
267 
268 // -------------------------------------------------------------------------
269 void OOrderColumn::construct()
270 {
271 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISASCENDING), PROPERTY_ID_ISASCENDING,
272         PropertyAttribute::READONLY,  const_cast< sal_Bool* >( &m_bAscending ),    ::getCppuType( reinterpret_cast< sal_Bool* >( NULL ) ) );
273     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TABLENAME),   PROPERTY_ID_TABLENAME,
274         PropertyAttribute::READONLY,  const_cast< ::rtl::OUString* >( &m_sTableName ),  ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
275 }
276 // -----------------------------------------------------------------------------
277 ::cppu::IPropertyArrayHelper* OOrderColumn::createArrayHelper() const
278 {
279     return doCreateArrayHelper();
280 }
281 // -----------------------------------------------------------------------------
282 ::cppu::IPropertyArrayHelper & SAL_CALL OOrderColumn::getInfoHelper()
283 {
284     OSL_ENSURE( !isNew(), "OOrderColumn::getInfoHelper: a *new* OrderColumn?" );
285 	return *OOrderColumn_PROP::getArrayHelper();
286 }
287 // -----------------------------------------------------------------------------
288 ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OOrderColumn::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)
289 {
290 	::com::sun::star::uno::Sequence< ::rtl::OUString > aSupported(1);
291 	aSupported[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.OrderColumn");
292 
293 	return aSupported;
294 }
295 // -----------------------------------------------------------------------------
296