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 : };
|