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 : :
60 : : #include <com/sun/star/sdbc/XRow.hpp>
61 : : #include <com/sun/star/sdbc/XParameters.hpp>
62 : : #include <com/sun/star/sdbcx/Privilege.hpp>
63 : : #include <com/sun/star/sdbcx/KeyType.hpp>
64 : : #include <com/sun/star/sdbc/KeyRule.hpp>
65 : : #include <com/sun/star/sdbc/DataType.hpp>
66 : :
67 : : #include "pq_xtables.hxx"
68 : : #include "pq_xviews.hxx"
69 : : #include "pq_xtable.hxx"
70 : : #include "pq_statics.hxx"
71 : : #include "pq_tools.hxx"
72 : :
73 : : using osl::MutexGuard;
74 : :
75 : : using rtl::OUString;
76 : : using rtl::OUStringBuffer;
77 : : using rtl::OUStringToOString;
78 : :
79 : : using com::sun::star::beans::XPropertySet;
80 : :
81 : : using com::sun::star::uno::Any;
82 : : using com::sun::star::uno::makeAny;
83 : : using com::sun::star::uno::UNO_QUERY;
84 : : using com::sun::star::uno::Type;
85 : : using com::sun::star::uno::XInterface;
86 : : using com::sun::star::uno::Reference;
87 : : using com::sun::star::uno::Sequence;
88 : : using com::sun::star::uno::RuntimeException;
89 : :
90 : : using com::sun::star::container::NoSuchElementException;
91 : : using com::sun::star::container::XEnumerationAccess;
92 : : using com::sun::star::container::XEnumeration;
93 : : using com::sun::star::lang::WrappedTargetException;
94 : :
95 : : using com::sun::star::sdbc::XRow;
96 : : // using com::sun::star::sdbc::DataType;
97 : : using com::sun::star::sdbc::XCloseable;
98 : : using com::sun::star::sdbc::XStatement;
99 : : using com::sun::star::sdbc::XResultSet;
100 : : using com::sun::star::sdbc::XParameters;
101 : : using com::sun::star::sdbc::XPreparedStatement;
102 : : using com::sun::star::sdbc::XDatabaseMetaData;
103 : : using com::sun::star::sdbcx::XColumnsSupplier;
104 : : using com::sun::star::sdbcx::XKeysSupplier;
105 : : using com::sun::star::sdbcx::XViewsSupplier;
106 : : // using com::sun::star::sdbcx::Privilege;
107 : :
108 : : namespace pq_sdbc_driver
109 : : {
110 : 0 : Tables::Tables(
111 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
112 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
113 : : ConnectionSettings *pSettings )
114 : 0 : : Container( refMutex, origin, pSettings, getStatics().TABLE )
115 : 0 : {}
116 : :
117 : 0 : Tables::~Tables()
118 : 0 : {}
119 : :
120 : 0 : void Tables::refresh()
121 : : throw (::com::sun::star::uno::RuntimeException)
122 : : {
123 : : try
124 : : {
125 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
126 : 0 : Statics & st = getStatics();
127 : :
128 : 0 : Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
129 : :
130 : : Reference< XResultSet > rs =
131 : 0 : meta->getTables( Any(), st.cPERCENT,st.cPERCENT, Sequence< OUString > () );
132 : :
133 : 0 : Reference< XRow > xRow( rs , UNO_QUERY );
134 : :
135 : 0 : String2IntMap map;
136 : :
137 : 0 : m_values = Sequence< com::sun::star::uno::Any > ();
138 : 0 : sal_Int32 tableIndex = 0;
139 : 0 : while( rs->next() )
140 : : {
141 : : // if creating all these tables turns out to have too bad performance, we might
142 : : // instead offer a factory interface
143 : : Table * pTable =
144 : 0 : new Table( m_refMutex, m_origin, m_pSettings );
145 : 0 : Reference< com::sun::star::beans::XPropertySet > prop = pTable;
146 : :
147 : 0 : OUString name = xRow->getString( TABLE_INDEX_NAME+1);
148 : 0 : OUString schema = xRow->getString( TABLE_INDEX_SCHEMA+1);
149 : : pTable->setPropertyValue_NoBroadcast_public(
150 : 0 : st.CATALOG_NAME , makeAny(xRow->getString( TABLE_INDEX_CATALOG+1) ) );
151 : 0 : pTable->setPropertyValue_NoBroadcast_public( st.NAME , makeAny( name ) );
152 : 0 : pTable->setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME , makeAny( schema ));
153 : : pTable->setPropertyValue_NoBroadcast_public(
154 : 0 : st.TYPE , makeAny( xRow->getString( TABLE_INDEX_TYPE+1) ) );
155 : : pTable->setPropertyValue_NoBroadcast_public(
156 : 0 : st.DESCRIPTION , makeAny( xRow->getString( TABLE_INDEX_REMARKS+1) ) );
157 : : pTable->setPropertyValue_NoBroadcast_public(
158 : : st.PRIVILEGES ,
159 : : makeAny( (sal_Int32)
160 : : ( com::sun::star::sdbcx::Privilege::SELECT |
161 : : com::sun::star::sdbcx::Privilege::INSERT |
162 : : com::sun::star::sdbcx::Privilege::UPDATE |
163 : : com::sun::star::sdbcx::Privilege::DELETE |
164 : : com::sun::star::sdbcx::Privilege::READ |
165 : : com::sun::star::sdbcx::Privilege::CREATE |
166 : : com::sun::star::sdbcx::Privilege::ALTER |
167 : : com::sun::star::sdbcx::Privilege::REFERENCE |
168 : 0 : com::sun::star::sdbcx::Privilege::DROP ) ) );
169 : :
170 : : {
171 : 0 : const int currentTableIndex = tableIndex++;
172 : : assert(currentTableIndex == m_values.getLength());
173 : 0 : m_values.realloc( tableIndex );
174 : 0 : m_values[currentTableIndex] = makeAny( prop );
175 : 0 : OUStringBuffer buf( name.getLength() + schema.getLength() + 1);
176 : 0 : buf.append( schema ).appendAscii( "." ).append( name );
177 : 0 : map[ buf.makeStringAndClear() ] = currentTableIndex;
178 : : }
179 : 0 : }
180 : 0 : m_name2index.swap( map );
181 : : }
182 : 0 : catch ( const com::sun::star::sdbc::SQLException & e )
183 : : {
184 : 0 : throw RuntimeException( e.Message , e.Context );
185 : : }
186 : :
187 : 0 : fire( RefreshedBroadcaster( *this ) );
188 : 0 : }
189 : :
190 : :
191 : 0 : static void appendColumnList(
192 : : OUStringBuffer &buf, const Reference< XColumnsSupplier > & columnSupplier, ConnectionSettings *settings )
193 : : {
194 : 0 : if( columnSupplier.is() )
195 : : {
196 : 0 : Reference< XEnumerationAccess > columns( columnSupplier->getColumns(),UNO_QUERY );
197 : 0 : if( columns.is() )
198 : : {
199 : 0 : Reference< XEnumeration > xEnum( columns->createEnumeration() );
200 : 0 : bool first = true;
201 : 0 : Statics & st = getStatics();
202 : :
203 : 0 : while( xEnum.is() && xEnum->hasMoreElements() )
204 : : {
205 : 0 : if( first )
206 : : {
207 : 0 : first = false;
208 : : }
209 : : else
210 : : {
211 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
212 : : }
213 : 0 : Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
214 : 0 : OUString name = extractStringProperty( column, st.NAME );
215 : 0 : OUString defaultValue = extractStringProperty( column, st.DEFAULT_VALUE );
216 : 0 : sal_Bool isNullable = extractBoolProperty( column, st.IS_NULLABLE );
217 : 0 : sal_Bool isAutoIncrement = extractBoolProperty( column, st.IS_AUTO_INCREMENT );
218 : :
219 : 0 : bufferQuoteIdentifier( buf, name, settings );
220 : :
221 : 0 : OUString type = sqltype2string( column );
222 : 0 : if( isAutoIncrement )
223 : : {
224 : 0 : sal_Int32 dataType = 0;
225 : 0 : column->getPropertyValue( st.TYPE ) >>= dataType;
226 : 0 : if( com::sun::star::sdbc::DataType::INTEGER == dataType )
227 : : {
228 : 0 : buf.appendAscii( " serial ");
229 : 0 : isNullable = sal_False;
230 : : }
231 : 0 : else if( com::sun::star::sdbc::DataType::BIGINT == dataType )
232 : : {
233 : 0 : buf.appendAscii( " serial8 " );
234 : 0 : isNullable = sal_False;
235 : : }
236 : : else
237 : 0 : buf.append( type );
238 : : }
239 : : else
240 : : {
241 : 0 : buf.append( type );
242 : : }
243 : 0 : if( defaultValue.getLength() )
244 : : {
245 : 0 : bufferQuoteConstant( buf, defaultValue, settings );
246 : : }
247 : :
248 : 0 : if( ! isNullable )
249 : : // buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " NULL " ) );
250 : : // else
251 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " NOT NULL " ) );
252 : :
253 : 0 : }
254 : 0 : }
255 : : }
256 : 0 : }
257 : :
258 : 0 : static void appendKeyList(
259 : : OUStringBuffer & buf, const Reference< XKeysSupplier > &keySupplier, ConnectionSettings *settings )
260 : : {
261 : 0 : if( keySupplier.is() )
262 : : {
263 : 0 : Reference< XEnumerationAccess > keys( keySupplier->getKeys(), UNO_QUERY );
264 : 0 : if(keys.is() )
265 : : {
266 : 0 : Reference< XEnumeration > xEnum = keys->createEnumeration();
267 : 0 : while( xEnum.is() && xEnum->hasMoreElements() )
268 : : {
269 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
270 : 0 : Reference< XPropertySet > key( xEnum->nextElement(), UNO_QUERY );
271 : 0 : bufferKey2TableConstraint( buf, key, settings );
272 : 0 : }
273 : 0 : }
274 : : }
275 : 0 : }
276 : :
277 : 0 : void Tables::appendByDescriptor(
278 : : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
279 : : throw (::com::sun::star::sdbc::SQLException,
280 : : ::com::sun::star::container::ElementExistException,
281 : : ::com::sun::star::uno::RuntimeException)
282 : : {
283 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
284 : : Reference< XStatement > stmt =
285 : 0 : m_origin->createStatement();
286 : :
287 : 0 : Statics &st = getStatics();
288 : 0 : OUString name,schema;
289 : 0 : descriptor->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
290 : 0 : descriptor->getPropertyValue( st.NAME ) >>= name;
291 : :
292 : 0 : TransactionGuard transaction( stmt );
293 : :
294 : 0 : OUStringBuffer buf( 128 );
295 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("CREATE TABLE" ) );
296 : 0 : bufferQuoteQualifiedIdentifier( buf, schema, name , m_pSettings);
297 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "(" ) );
298 : :
299 : : // columns
300 : 0 : Reference< XColumnsSupplier > supplier( descriptor, UNO_QUERY );
301 : 0 : appendColumnList( buf, supplier, m_pSettings );
302 : :
303 : 0 : appendKeyList( buf, Reference< XKeysSupplier >( descriptor, UNO_QUERY ), m_pSettings );
304 : :
305 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ") " ) );
306 : : // execute the creation !
307 : 0 : transaction.executeUpdate( buf.makeStringAndClear() );
308 : :
309 : : // description ....
310 : 0 : OUString description = extractStringProperty( descriptor, st.DESCRIPTION );
311 : 0 : if( description.getLength() )
312 : : {
313 : 0 : buf = OUStringBuffer( 128 );
314 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "COMMENT ON TABLE" ) );
315 : 0 : bufferQuoteQualifiedIdentifier( buf, schema, name, m_pSettings );
316 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "IS " ) );
317 : 0 : bufferQuoteConstant( buf, description, m_pSettings);
318 : :
319 : 0 : transaction.executeUpdate( buf.makeStringAndClear() );
320 : : }
321 : :
322 : : // column descriptions
323 : 0 : if( supplier.is() )
324 : : {
325 : 0 : Reference< XEnumerationAccess > columns( supplier->getColumns(),UNO_QUERY );
326 : 0 : if( columns.is() )
327 : : {
328 : 0 : Reference< XEnumeration > xEnum( columns->createEnumeration() );
329 : 0 : while( xEnum.is() && xEnum->hasMoreElements() )
330 : : {
331 : 0 : Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
332 : : // help text seems to be used by OOo rather than Description
333 : : // OUString description = extractStringProperty( column, st.HELP_TEXT );
334 : 0 : OUString helpText = extractStringProperty( column,st.DESCRIPTION );
335 : 0 : if( description.getLength() )
336 : : {
337 : 0 : buf = OUStringBuffer( 128 );
338 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "COMMENT ON COLUMN " ) );
339 : : bufferQuoteQualifiedIdentifier(
340 : 0 : buf, schema, name, extractStringProperty( column, st.NAME ), m_pSettings );
341 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "IS " ) );
342 : 0 : bufferQuoteConstant( buf, description, m_pSettings );
343 : 0 : transaction.executeUpdate( buf.makeStringAndClear() );
344 : : }
345 : 0 : }
346 : 0 : }
347 : : }
348 : :
349 : 0 : transaction.commit();
350 : :
351 : 0 : disposeNoThrow( stmt );
352 : : // TODO: cheaper recalculate
353 : : // Container::append( concatQualified( schema, name ), descriptor ); // maintain the lists
354 : 0 : refresh();
355 : :
356 : : // increase the vector
357 : : // sal_Int32 index = m_values.getLength();
358 : : // m_values.realloc( index + 1 );
359 : :
360 : : // Table * pTable =
361 : : // new Table( m_refMutex, m_origin, m_pSettings, false /*modifiable*/ );
362 : : // Reference< com::sun::star::beans::XPropertySet > prop = pTable;
363 : : // copyProperties( pTable, descriptor );
364 : : // m_values[index] = makeAny( prop );
365 : : // OUStringBuffer buf( name.getLength() + 1 + schema.getLength() );
366 : : // buf.append( schema ).appendAscii( "." ).append( name );
367 : : // m_name2index[ buf.makeStringAndClear() ] = index;
368 : 0 : }
369 : :
370 : : // void Tables::dropByName( const ::rtl::OUString& elementName )
371 : : // throw (::com::sun::star::sdbc::SQLException,
372 : : // ::com::sun::star::container::NoSuchElementException,
373 : : // ::com::sun::star::uno::RuntimeException)
374 : : // {
375 : : // String2IntMap::const_iterator ii = m_name2index.find( elementName );
376 : : // if( ii == m_name2index.end() )
377 : : // {
378 : : // OUStringBuffer buf( 128 );
379 : : // buf.appendAscii( "Table " );
380 : : // buf.append( elementName );
381 : : // buf.appendAscii( " is unknown, so it can't be dropped" );
382 : : // throw com::sun::star::container::NoSuchElementException(
383 : : // buf.makeStringAndClear(), *this );
384 : : // }
385 : : // dropByIndex( ii->second );
386 : : // }
387 : :
388 : 0 : void Tables::dropByIndex( sal_Int32 index )
389 : : throw (::com::sun::star::sdbc::SQLException,
390 : : ::com::sun::star::lang::IndexOutOfBoundsException,
391 : : ::com::sun::star::uno::RuntimeException)
392 : : {
393 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
394 : 0 : if( index < 0 || index >= m_values.getLength() )
395 : : {
396 : 0 : OUStringBuffer buf( 128 );
397 : 0 : buf.appendAscii( "TABLES: Index out of range (allowed 0 to " );
398 : 0 : buf.append( (sal_Int32) (m_values.getLength() -1) );
399 : 0 : buf.appendAscii( ", got " );
400 : 0 : buf.append( index );
401 : 0 : buf.appendAscii( ")" );
402 : : throw com::sun::star::lang::IndexOutOfBoundsException(
403 : 0 : buf.makeStringAndClear(), *this );
404 : : }
405 : :
406 : 0 : Reference< XPropertySet > set;
407 : 0 : m_values[index] >>= set;
408 : 0 : Statics &st = getStatics();
409 : 0 : OUString name,schema;
410 : 0 : set->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
411 : 0 : set->getPropertyValue( st.NAME ) >>= name;
412 : 0 : if( extractStringProperty( set, st.TYPE ).equals( st.VIEW ) && m_pSettings->views.is() )
413 : : {
414 : 0 : m_pSettings->pViewsImpl->dropByName( concatQualified( schema, name ) );
415 : : }
416 : : else
417 : : {
418 : 0 : OUStringBuffer update( 128 );
419 : 0 : update.appendAscii( RTL_CONSTASCII_STRINGPARAM( "DROP " ) );
420 : 0 : if( extractStringProperty( set, st.TYPE ).equals( st.VIEW ) )
421 : 0 : update.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VIEW " ) );
422 : : else
423 : 0 : update.appendAscii( RTL_CONSTASCII_STRINGPARAM( "TABLE " ) );
424 : 0 : bufferQuoteQualifiedIdentifier( update, schema, name, m_pSettings );
425 : 0 : Reference< XStatement > stmt = m_origin->createStatement( );
426 : 0 : DisposeGuard dispGuard( stmt );
427 : 0 : stmt->executeUpdate( update.makeStringAndClear() );
428 : : }
429 : :
430 : 0 : Container::dropByIndex( index );
431 : 0 : }
432 : :
433 : :
434 : 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > Tables::createDataDescriptor()
435 : : throw (::com::sun::star::uno::RuntimeException)
436 : : {
437 : 0 : return new TableDescriptor( m_refMutex, m_origin, m_pSettings );
438 : : }
439 : :
440 : 0 : Reference< com::sun::star::container::XNameAccess > Tables::create(
441 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
442 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
443 : : ConnectionSettings *pSettings,
444 : : Tables **ppTables)
445 : : {
446 : 0 : *ppTables = new Tables( refMutex, origin, pSettings );
447 : 0 : Reference< com::sun::star::container::XNameAccess > ret = *ppTables;
448 : 0 : (*ppTables)->refresh();
449 : :
450 : 0 : return ret;
451 : : }
452 : :
453 : 0 : void Tables::disposing()
454 : : {
455 : 0 : Container::disposing();
456 : 0 : }
457 : :
458 : : };
|