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