Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * Effective License of whole file:
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License version 2.1, as published by the Free Software Foundation.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 : : * MA 02111-1307 USA
19 : : *
20 : : * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
21 : : *
22 : : * The Contents of this file are made available subject to the terms of
23 : : * the GNU Lesser General Public License Version 2.1
24 : : *
25 : : * Copyright: 2000 by Sun Microsystems, Inc.
26 : : *
27 : : * Contributor(s): Joerg Budischewski
28 : : *
29 : : * All parts contributed on or after August 2011:
30 : : *
31 : : * Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
32 : : *
33 : : * The contents of this file are subject to the Mozilla Public License Version
34 : : * 1.1 (the "License"); you may not use this file except in compliance with
35 : : * the License or as specified alternatively below. You may obtain a copy of
36 : : * the License at http://www.mozilla.org/MPL/
37 : : *
38 : : * Software distributed under the License is distributed on an "AS IS" basis,
39 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40 : : * for the specific language governing rights and limitations under the
41 : : * License.
42 : : *
43 : : * Major Contributor(s):
44 : : * [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
45 : : *
46 : : * All Rights Reserved.
47 : : *
48 : : * For minor contributions see the git repository.
49 : : *
50 : : * Alternatively, the contents of this file may be used under the terms of
51 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
52 : : * the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
53 : : * in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
54 : : * instead of those above.
55 : : *
56 : : ************************************************************************/
57 : :
58 : : #include <rtl/ustrbuf.hxx>
59 : : #include <rtl/strbuf.hxx>
60 : :
61 : : #include <com/sun/star/sdbc/XRow.hpp>
62 : : #include <com/sun/star/sdbc/XParameters.hpp>
63 : : #include <com/sun/star/sdbc/DataType.hpp>
64 : : #include <com/sun/star/sdbc/ColumnValue.hpp>
65 : :
66 : : #include "pq_xcolumns.hxx"
67 : : #include "pq_xkeycolumns.hxx"
68 : : #include "pq_xkeycolumn.hxx"
69 : : #include "pq_statics.hxx"
70 : : #include "pq_tools.hxx"
71 : :
72 : : using osl::MutexGuard;
73 : :
74 : : using rtl::OUString;
75 : : using rtl::OUStringBuffer;
76 : : using rtl::OUStringToOString;
77 : :
78 : : using com::sun::star::beans::XPropertySet;
79 : :
80 : : using com::sun::star::uno::Any;
81 : : using com::sun::star::uno::makeAny;
82 : : using com::sun::star::uno::UNO_QUERY;
83 : : using com::sun::star::uno::Type;
84 : : using com::sun::star::uno::XInterface;
85 : : using com::sun::star::uno::Reference;
86 : : using com::sun::star::uno::Sequence;
87 : : using com::sun::star::uno::RuntimeException;
88 : :
89 : : using com::sun::star::container::NoSuchElementException;
90 : : using com::sun::star::lang::WrappedTargetException;
91 : :
92 : : using com::sun::star::sdbc::XRow;
93 : : using com::sun::star::sdbc::XCloseable;
94 : : using com::sun::star::sdbc::XStatement;
95 : : using com::sun::star::sdbc::XResultSet;
96 : : using com::sun::star::sdbc::XParameters;
97 : : using com::sun::star::sdbc::XPreparedStatement;
98 : : using com::sun::star::sdbc::XDatabaseMetaData;
99 : : using com::sun::star::sdbc::SQLException;
100 : :
101 : : namespace pq_sdbc_driver
102 : : {
103 : : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
104 : :
105 : 0 : KeyColumns::KeyColumns(
106 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
107 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
108 : : ConnectionSettings *pSettings,
109 : : const rtl::OUString &schemaName,
110 : : const rtl::OUString &tableName,
111 : : const Sequence< rtl::OUString > &columnNames,
112 : : const Sequence< rtl::OUString > &foreignColumnNames )
113 : : : Container( refMutex, origin, pSettings, ASCII_STR( "KEY_COLUMN" ) ),
114 : : m_schemaName( schemaName ),
115 : : m_tableName( tableName ),
116 : : m_columnNames( columnNames ),
117 : 0 : m_foreignColumnNames( foreignColumnNames )
118 : 0 : {}
119 : :
120 : 0 : KeyColumns::~KeyColumns()
121 : 0 : {}
122 : :
123 : :
124 : 0 : void KeyColumns::refresh()
125 : : throw (::com::sun::star::uno::RuntimeException)
126 : : {
127 : : try
128 : : {
129 : 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
130 : : {
131 : 0 : rtl::OStringBuffer buf;
132 : 0 : buf.append( "sdbcx.KeyColumns get refreshed for table " );
133 : 0 : buf.append( OUStringToOString( m_schemaName, m_pSettings->encoding ) );
134 : 0 : buf.append( "." );
135 : 0 : buf.append( OUStringToOString( m_tableName, m_pSettings->encoding ) );
136 : 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear().getStr() );
137 : : }
138 : :
139 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
140 : :
141 : 0 : Statics &st = getStatics();
142 : 0 : Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
143 : :
144 : : Reference< XResultSet > rs =
145 : 0 : meta->getColumns( Any(), m_schemaName, m_tableName, st.cPERCENT );
146 : :
147 : 0 : DisposeGuard disposeIt( rs );
148 : 0 : Reference< XRow > xRow( rs , UNO_QUERY );
149 : :
150 : 0 : String2IntMap map;
151 : :
152 : 0 : m_values = Sequence< com::sun::star::uno::Any > ();
153 : 0 : sal_Int32 columnIndex = 0;
154 : 0 : while( rs->next() )
155 : : {
156 : 0 : OUString columnName = xRow->getString( 4 );
157 : :
158 : : int keyindex;
159 : 0 : for( keyindex = 0 ; keyindex < m_columnNames.getLength() ; keyindex ++ )
160 : : {
161 : 0 : if( columnName == m_columnNames[keyindex] )
162 : 0 : break;
163 : : }
164 : 0 : if( m_columnNames.getLength() == keyindex )
165 : 0 : continue;
166 : :
167 : : KeyColumn * pKeyColumn =
168 : 0 : new KeyColumn( m_refMutex, m_origin, m_pSettings );
169 : 0 : Reference< com::sun::star::beans::XPropertySet > prop = pKeyColumn;
170 : :
171 : 0 : OUString name = columnMetaData2SDBCX( pKeyColumn, xRow );
172 : 0 : if( keyindex < m_foreignColumnNames.getLength() )
173 : : {
174 : : pKeyColumn->setPropertyValue_NoBroadcast_public(
175 : 0 : st.RELATED_COLUMN, makeAny( m_foreignColumnNames[keyindex]) );
176 : : }
177 : :
178 : : {
179 : 0 : const int currentColumnIndex = columnIndex++;
180 : : assert(currentColumnIndex == m_values.getLength());
181 : 0 : m_values.realloc( columnIndex );
182 : 0 : m_values[currentColumnIndex] = makeAny( prop );
183 : 0 : map[ name ] = currentColumnIndex;
184 : : }
185 : 0 : }
186 : 0 : m_name2index.swap( map );
187 : : }
188 : 0 : catch ( com::sun::star::sdbc::SQLException & e )
189 : : {
190 : 0 : throw RuntimeException( e.Message , e.Context );
191 : : }
192 : :
193 : 0 : fire( RefreshedBroadcaster( *this ) );
194 : 0 : }
195 : :
196 : :
197 : : // void alterColumnByDescriptor(
198 : : // const OUString & schemaName,
199 : : // const OUString & tableName,
200 : : // rtl_TextEncoding encoding,
201 : : // const Reference< XStatement > &stmt,
202 : : // const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > & past,
203 : : // const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > & future)
204 : : // {
205 : : // Statics & st = getStatics();
206 : :
207 : : // // if( past->getPropertyValue( st.TABLE_NAME ) != future->getPropertyValue( st.TABLE_NAME ) ||
208 : : // // past->getPropertyValue( st.SCHEMA_NAME ) != future->getPropertyValue( st.SCHEMA_NAME ))
209 : : // // {
210 : : // // OUStringBuffer buf(128);
211 : : // // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Can't move column " ) );
212 : : // // buf.append( extractStringProperty( past, st.COLUMN_NAME ) );
213 : : // // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " from table " ) );
214 : : // // buf.append( extractStringProperty( past, st.TABLE_NAME ) );
215 : : // // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " to table " ) );
216 : : // // buf.append( extractStringProperty( past, st.TABLE_NAME ) );
217 : : // // throw SQLException( buf.makeStringAndClear(), Reference< XInterface > () );
218 : : // // }
219 : :
220 : : // // OUString tableName = extractStringProperty( past, st.TABLE_NAME );
221 : : // // OUString schemaName = extractStringProperty( past, st.SCHEMA_NAME );
222 : : // OUString pastColumnName = extractStringProperty( past, st.NAME );
223 : : // OUString futureColumnName = extractStringProperty( future, st.NAME );
224 : : // OUString pastTypeName = sqltype2string( past );
225 : : // OUString futureTypeName = sqltype2string( future );
226 : :
227 : : // TransactionGuard transaction( stmt );
228 : :
229 : : // OUStringBuffer buf( 128 );
230 : : // if( ! pastColumnName.getLength())
231 : : // {
232 : : // // create a new column
233 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE" ) );
234 : : // bufferQuoteQualifiedIdentifier( buf, schemaName, tableName );
235 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ADD COLUMN" ) );
236 : : // bufferQuoteIdentifier( buf, futureColumnName );
237 : : // buf.append( futureTypeName );
238 : : // transaction.executeUpdate( buf.makeStringAndClear() );
239 : : // }
240 : : // else
241 : : // {
242 : : // if( pastTypeName != futureTypeName )
243 : : // {
244 : : // throw RuntimeException(
245 : : // ASCII_STR( "Can't modify column types, drop the column and create a new one" ),
246 : : // Reference< XInterface > () );
247 : : // }
248 : :
249 : : // if( pastColumnName != futureColumnName )
250 : : // {
251 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE" ) );
252 : : // bufferQuoteQualifiedIdentifier( buf, schemaName, tableName );
253 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "RENAME COLUMN" ) );
254 : : // bufferQuoteIdentifier( buf, pastColumnName );
255 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "TO" ) );
256 : : // bufferQuoteIdentifier( buf, futureColumnName );
257 : : // transaction.executeUpdate( buf.makeStringAndClear() );
258 : : // }
259 : : // }
260 : :
261 : : // OUString futureDefaultValue = extractStringProperty( future, st.DEFAULT_VALUE );
262 : : // OUString pastDefaultValue = extractStringProperty( past, st.DEFAULT_VALUE );
263 : : // if( futureDefaultValue != pastDefaultValue )
264 : : // {
265 : : // buf = OUStringBuffer( 128 );
266 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE" ) );
267 : : // bufferQuoteQualifiedIdentifier( buf, schemaName, tableName );
268 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER COLUMN" ) );
269 : : // bufferQuoteIdentifier( buf, futureColumnName );
270 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET DEFAULT " ) );
271 : : // // default value is not quoted, caller needs to quote himself (otherwise
272 : : // // how to pass e.g. nextval('something' ) ????
273 : : // buf.append( futureDefaultValue );
274 : : // // bufferQuoteConstant( buf, defaultValue, encoding );
275 : : // transaction.executeUpdate( buf.makeStringAndClear() );
276 : : // }
277 : :
278 : : // sal_Int32 futureNullable = extractIntProperty( future, st.IS_NULLABLE );
279 : : // sal_Int32 pastNullable = extractIntProperty( past, st.IS_NULLABLE );
280 : : // if( futureNullable != pastNullable )
281 : : // {
282 : : // buf = OUStringBuffer( 128 );
283 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE" ) );
284 : : // bufferQuoteQualifiedIdentifier( buf, schemaName, tableName );
285 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER COLUMN" ) );
286 : : // bufferQuoteIdentifier( buf, futureColumnName );
287 : : // if( futureNullable == com::sun::star::sdbc::ColumnValue::NO_NULLS )
288 : : // {
289 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SET" ) );
290 : : // }
291 : : // else
292 : : // {
293 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "DROP" ) );
294 : : // }
295 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " NOT NULL" ) );
296 : : // transaction.executeUpdate( buf.makeStringAndClear() );
297 : : // }
298 : :
299 : : // OUString futureComment = extractStringProperty( future, st.DESCRIPTION );
300 : : // OUString pastComment = extractStringProperty( past, st.DESCRIPTION );
301 : : // if( futureComment != pastComment )
302 : : // {
303 : : // buf = OUStringBuffer( 128 );
304 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "COMMENT ON COLUMN" ) );
305 : : // bufferQuoteQualifiedIdentifier( buf, schemaName, tableName , futureColumnName );
306 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "IS " ) );
307 : : // bufferQuoteConstant( buf, futureComment,encoding);
308 : : // transaction.executeUpdate( buf.makeStringAndClear() );
309 : : // }
310 : : // transaction.commit();
311 : : // }
312 : :
313 : 0 : void KeyColumns::appendByDescriptor(
314 : : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& future )
315 : : throw (::com::sun::star::sdbc::SQLException,
316 : : ::com::sun::star::container::ElementExistException,
317 : : ::com::sun::star::uno::RuntimeException)
318 : : {
319 : : (void) future;
320 : : throw com::sun::star::sdbc::SQLException(
321 : : ASCII_STR( "KeyColumns::appendByDescriptor not implemented yet" ),
322 : 0 : *this, OUString(), 1, Any() );
323 : :
324 : : // osl::MutexGuard guard( m_refMutex->mutex );
325 : : // Statics & st = getStatics();
326 : : // Reference< XPropertySet > past = createDataDescriptor();
327 : : // past->setPropertyValue( st.IS_NULLABLE, makeAny( com::sun::star::sdbc::ColumnValue::NULLABLE ) );
328 : : // alterColumnByDescriptor(
329 : : // m_schemaName, m_tableName, m_pSettings->encoding, m_origin->createStatement() , past, future );
330 : :
331 : : }
332 : :
333 : :
334 : 0 : void KeyColumns::dropByIndex( sal_Int32 index )
335 : : throw (::com::sun::star::sdbc::SQLException,
336 : : ::com::sun::star::lang::IndexOutOfBoundsException,
337 : : ::com::sun::star::uno::RuntimeException)
338 : : {
339 : : (void) index;
340 : : throw com::sun::star::sdbc::SQLException(
341 : : ASCII_STR( "KeyColumns::dropByIndex not implemented yet" ),
342 : 0 : *this, OUString(), 1, Any() );
343 : : // osl::MutexGuard guard( m_refMutex->mutex );
344 : : // if( index < 0 || index >= m_values.getLength() )
345 : : // {
346 : : // OUStringBuffer buf( 128 );
347 : : // buf.appendAscii( "COLUMNS: Index out of range (allowed 0 to " );
348 : : // buf.append((sal_Int32)(m_values.getLength() -1) );
349 : : // buf.appendAscii( ", got " );
350 : : // buf.append( index );
351 : : // buf.appendAscii( ")" );
352 : : // throw com::sun::star::lang::IndexOutOfBoundsException(
353 : : // buf.makeStringAndClear(), *this );
354 : : // }
355 : :
356 : : // Reference< XPropertySet > set;
357 : : // m_values[index] >>= set;
358 : : // Statics &st = getStatics();
359 : : // OUString name;
360 : : // set->getPropertyValue( st.NAME ) >>= name;
361 : :
362 : : // OUStringBuffer update( 128 );
363 : : // update.appendAscii( "ALTER TABLE ONLY");
364 : : // bufferQuoteQualifiedIdentifier( update, m_schemaName, m_tableName );
365 : : // update.appendAscii( "DROP COLUMN" );
366 : : // bufferQuoteIdentifier( update, name );
367 : : // Reference< XStatement > stmt = m_origin->createStatement( );
368 : : // DisposeGuard disposeIt( stmt );
369 : : // stmt->executeUpdate( update.makeStringAndClear() );
370 : :
371 : : }
372 : :
373 : :
374 : 0 : Reference< ::com::sun::star::beans::XPropertySet > KeyColumns::createDataDescriptor()
375 : : throw (::com::sun::star::uno::RuntimeException)
376 : : {
377 : 0 : return new KeyColumnDescriptor( m_refMutex, m_origin, m_pSettings );
378 : : }
379 : :
380 : 0 : Reference< com::sun::star::container::XNameAccess > KeyColumns::create(
381 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
382 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
383 : : ConnectionSettings *pSettings,
384 : : const rtl::OUString &schemaName,
385 : : const rtl::OUString &tableName,
386 : : const Sequence< rtl::OUString > &columnNames ,
387 : : const Sequence< rtl::OUString > &foreignColumnNames )
388 : : {
389 : : KeyColumns *pKeyColumns = new KeyColumns(
390 : 0 : refMutex, origin, pSettings, schemaName, tableName, columnNames, foreignColumnNames );
391 : 0 : Reference< com::sun::star::container::XNameAccess > ret = pKeyColumns;
392 : 0 : pKeyColumns->refresh();
393 : :
394 : 0 : return ret;
395 : : }
396 : :
397 : : //_______________________________________________________________________________________
398 : 0 : KeyColumnDescriptors::KeyColumnDescriptors(
399 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
400 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
401 : : ConnectionSettings *pSettings )
402 : 0 : : Container( refMutex, origin, pSettings, ASCII_STR( "KEY_COLUMN" ) )
403 : 0 : {}
404 : :
405 : 0 : Reference< ::com::sun::star::beans::XPropertySet > KeyColumnDescriptors::createDataDescriptor()
406 : : throw (::com::sun::star::uno::RuntimeException)
407 : : {
408 : 0 : return new KeyColumnDescriptor( m_refMutex, m_origin, m_pSettings );
409 : : }
410 : : };
|