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 : * This Source Code Form is subject to the terms of the Mozilla Public
32 : * License, v. 2.0. If a copy of the MPL was not distributed with this
33 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
34 : *
35 : ************************************************************************/
36 :
37 : #include <rtl/ustrbuf.hxx>
38 :
39 : #include <com/sun/star/sdbc/XRow.hpp>
40 : #include <com/sun/star/sdbc/XParameters.hpp>
41 : #include <com/sun/star/sdbcx/Privilege.hpp>
42 : #include <com/sun/star/sdbcx/KeyType.hpp>
43 : #include <com/sun/star/sdbc/KeyRule.hpp>
44 : #include <com/sun/star/sdbc/DataType.hpp>
45 :
46 : #include "pq_xtables.hxx"
47 : #include "pq_xviews.hxx"
48 : #include "pq_xtable.hxx"
49 : #include "pq_statics.hxx"
50 : #include "pq_tools.hxx"
51 :
52 : using osl::MutexGuard;
53 :
54 : using com::sun::star::beans::XPropertySet;
55 :
56 : using com::sun::star::uno::Any;
57 : using com::sun::star::uno::makeAny;
58 : using com::sun::star::uno::UNO_QUERY;
59 : using com::sun::star::uno::Type;
60 : using com::sun::star::uno::XInterface;
61 : using com::sun::star::uno::Reference;
62 : using com::sun::star::uno::Sequence;
63 : using com::sun::star::uno::RuntimeException;
64 :
65 : using com::sun::star::container::NoSuchElementException;
66 : using com::sun::star::container::XEnumerationAccess;
67 : using com::sun::star::container::XEnumeration;
68 : using com::sun::star::lang::WrappedTargetException;
69 :
70 : using com::sun::star::sdbc::XRow;
71 : using com::sun::star::sdbc::XCloseable;
72 : using com::sun::star::sdbc::XStatement;
73 : using com::sun::star::sdbc::XResultSet;
74 : using com::sun::star::sdbc::XParameters;
75 : using com::sun::star::sdbc::XPreparedStatement;
76 : using com::sun::star::sdbc::XDatabaseMetaData;
77 : using com::sun::star::sdbcx::XColumnsSupplier;
78 : using com::sun::star::sdbcx::XKeysSupplier;
79 : using com::sun::star::sdbcx::XViewsSupplier;
80 :
81 : namespace pq_sdbc_driver
82 : {
83 0 : Tables::Tables(
84 : const ::rtl::Reference< RefCountedMutex > & refMutex,
85 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
86 : ConnectionSettings *pSettings )
87 0 : : Container( refMutex, origin, pSettings, getStatics().TABLE )
88 0 : {}
89 :
90 0 : Tables::~Tables()
91 0 : {}
92 :
93 0 : void Tables::refresh()
94 : throw (::com::sun::star::uno::RuntimeException, std::exception)
95 : {
96 : try
97 : {
98 0 : osl::MutexGuard guard( m_refMutex->mutex );
99 0 : Statics & st = getStatics();
100 :
101 0 : Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
102 :
103 : Reference< XResultSet > rs =
104 0 : meta->getTables( Any(), st.cPERCENT,st.cPERCENT, Sequence< OUString > () );
105 :
106 0 : Reference< XRow > xRow( rs , UNO_QUERY );
107 :
108 0 : String2IntMap map;
109 :
110 0 : m_values = Sequence< com::sun::star::uno::Any > ();
111 0 : sal_Int32 tableIndex = 0;
112 0 : while( rs->next() )
113 : {
114 : // if creating all these tables turns out to have too bad performance, we might
115 : // instead offer a factory interface
116 : Table * pTable =
117 0 : new Table( m_refMutex, m_origin, m_pSettings );
118 0 : Reference< com::sun::star::beans::XPropertySet > prop = pTable;
119 :
120 0 : OUString name = xRow->getString( TABLE_INDEX_NAME+1);
121 0 : OUString schema = xRow->getString( TABLE_INDEX_SCHEMA+1);
122 : pTable->setPropertyValue_NoBroadcast_public(
123 0 : st.CATALOG_NAME , makeAny(xRow->getString( TABLE_INDEX_CATALOG+1) ) );
124 0 : pTable->setPropertyValue_NoBroadcast_public( st.NAME , makeAny( name ) );
125 0 : pTable->setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME , makeAny( schema ));
126 : pTable->setPropertyValue_NoBroadcast_public(
127 0 : st.TYPE , makeAny( xRow->getString( TABLE_INDEX_TYPE+1) ) );
128 : pTable->setPropertyValue_NoBroadcast_public(
129 0 : st.DESCRIPTION , makeAny( xRow->getString( TABLE_INDEX_REMARKS+1) ) );
130 : pTable->setPropertyValue_NoBroadcast_public(
131 : st.PRIVILEGES ,
132 : makeAny( (sal_Int32)
133 : ( com::sun::star::sdbcx::Privilege::SELECT |
134 : com::sun::star::sdbcx::Privilege::INSERT |
135 : com::sun::star::sdbcx::Privilege::UPDATE |
136 : com::sun::star::sdbcx::Privilege::DELETE |
137 : com::sun::star::sdbcx::Privilege::READ |
138 : com::sun::star::sdbcx::Privilege::CREATE |
139 : com::sun::star::sdbcx::Privilege::ALTER |
140 : com::sun::star::sdbcx::Privilege::REFERENCE |
141 0 : com::sun::star::sdbcx::Privilege::DROP ) ) );
142 :
143 : {
144 0 : const int currentTableIndex = tableIndex++;
145 : assert(currentTableIndex == m_values.getLength());
146 0 : m_values.realloc( tableIndex );
147 0 : m_values[currentTableIndex] = makeAny( prop );
148 0 : OUStringBuffer buf( name.getLength() + schema.getLength() + 1);
149 0 : buf.append( schema + "." + name );
150 0 : map[ buf.makeStringAndClear() ] = currentTableIndex;
151 : }
152 0 : }
153 0 : m_name2index.swap( map );
154 : }
155 0 : catch ( const com::sun::star::sdbc::SQLException & e )
156 : {
157 0 : throw RuntimeException( e.Message , e.Context );
158 : }
159 :
160 0 : fire( RefreshedBroadcaster( *this ) );
161 0 : }
162 :
163 :
164 0 : static void appendColumnList(
165 : OUStringBuffer &buf, const Reference< XColumnsSupplier > & columnSupplier, ConnectionSettings *settings )
166 : {
167 0 : if( columnSupplier.is() )
168 : {
169 0 : Reference< XEnumerationAccess > columns( columnSupplier->getColumns(),UNO_QUERY );
170 0 : if( columns.is() )
171 : {
172 0 : Reference< XEnumeration > xEnum( columns->createEnumeration() );
173 0 : bool first = true;
174 0 : Statics & st = getStatics();
175 :
176 0 : while( xEnum.is() && xEnum->hasMoreElements() )
177 : {
178 0 : if( first )
179 : {
180 0 : first = false;
181 : }
182 : else
183 : {
184 0 : buf.append( ", " );
185 : }
186 0 : Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
187 0 : OUString name = extractStringProperty( column, st.NAME );
188 0 : OUString defaultValue = extractStringProperty( column, st.DEFAULT_VALUE );
189 0 : sal_Bool isNullable = extractBoolProperty( column, st.IS_NULLABLE );
190 0 : sal_Bool isAutoIncrement = extractBoolProperty( column, st.IS_AUTO_INCREMENT );
191 :
192 0 : bufferQuoteIdentifier( buf, name, settings );
193 :
194 0 : OUString type = sqltype2string( column );
195 0 : if( isAutoIncrement )
196 : {
197 0 : sal_Int32 dataType = 0;
198 0 : column->getPropertyValue( st.TYPE ) >>= dataType;
199 0 : if( com::sun::star::sdbc::DataType::INTEGER == dataType )
200 : {
201 0 : buf.append( " serial ");
202 0 : isNullable = sal_False;
203 : }
204 0 : else if( com::sun::star::sdbc::DataType::BIGINT == dataType )
205 : {
206 0 : buf.append( " serial8 " );
207 0 : isNullable = sal_False;
208 : }
209 : else
210 0 : buf.append( type );
211 : }
212 : else
213 : {
214 0 : buf.append( type );
215 : }
216 0 : if( !defaultValue.isEmpty() )
217 : {
218 0 : bufferQuoteConstant( buf, defaultValue, settings );
219 : }
220 :
221 0 : if( ! isNullable )
222 0 : buf.append( " NOT NULL " );
223 :
224 0 : }
225 0 : }
226 : }
227 0 : }
228 :
229 0 : static void appendKeyList(
230 : OUStringBuffer & buf, const Reference< XKeysSupplier > &keySupplier, ConnectionSettings *settings )
231 : {
232 0 : if( keySupplier.is() )
233 : {
234 0 : Reference< XEnumerationAccess > keys( keySupplier->getKeys(), UNO_QUERY );
235 0 : if(keys.is() )
236 : {
237 0 : Reference< XEnumeration > xEnum = keys->createEnumeration();
238 0 : while( xEnum.is() && xEnum->hasMoreElements() )
239 : {
240 0 : buf.append( ", " );
241 0 : Reference< XPropertySet > key( xEnum->nextElement(), UNO_QUERY );
242 0 : bufferKey2TableConstraint( buf, key, settings );
243 0 : }
244 0 : }
245 : }
246 0 : }
247 :
248 0 : void Tables::appendByDescriptor(
249 : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
250 : throw (::com::sun::star::sdbc::SQLException,
251 : ::com::sun::star::container::ElementExistException,
252 : ::com::sun::star::uno::RuntimeException, std::exception)
253 : {
254 0 : osl::MutexGuard guard( m_refMutex->mutex );
255 : Reference< XStatement > stmt =
256 0 : m_origin->createStatement();
257 :
258 0 : Statics &st = getStatics();
259 0 : OUString name,schema;
260 0 : descriptor->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
261 0 : descriptor->getPropertyValue( st.NAME ) >>= name;
262 :
263 0 : TransactionGuard transaction( stmt );
264 :
265 0 : OUStringBuffer buf( 128 );
266 0 : buf.append( "CREATE TABLE" );
267 0 : bufferQuoteQualifiedIdentifier( buf, schema, name , m_pSettings);
268 0 : buf.append( "(" );
269 :
270 : // columns
271 0 : Reference< XColumnsSupplier > supplier( descriptor, UNO_QUERY );
272 0 : appendColumnList( buf, supplier, m_pSettings );
273 :
274 0 : appendKeyList( buf, Reference< XKeysSupplier >( descriptor, UNO_QUERY ), m_pSettings );
275 :
276 0 : buf.append( ") " );
277 : // execute the creation !
278 0 : transaction.executeUpdate( buf.makeStringAndClear() );
279 :
280 : // description ....
281 0 : OUString description = extractStringProperty( descriptor, st.DESCRIPTION );
282 0 : if( !description.isEmpty() )
283 : {
284 0 : buf = OUStringBuffer( 128 );
285 0 : buf.append( "COMMENT ON TABLE" );
286 0 : bufferQuoteQualifiedIdentifier( buf, schema, name, m_pSettings );
287 0 : buf.append( "IS " );
288 0 : bufferQuoteConstant( buf, description, m_pSettings);
289 :
290 0 : transaction.executeUpdate( buf.makeStringAndClear() );
291 : }
292 :
293 : // column descriptions
294 0 : if( supplier.is() )
295 : {
296 0 : Reference< XEnumerationAccess > columns( supplier->getColumns(),UNO_QUERY );
297 0 : if( columns.is() )
298 : {
299 0 : Reference< XEnumeration > xEnum( columns->createEnumeration() );
300 0 : while( xEnum.is() && xEnum->hasMoreElements() )
301 : {
302 0 : Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
303 0 : description = extractStringProperty( column,st.DESCRIPTION );
304 0 : if( !description.isEmpty() )
305 : {
306 0 : buf = OUStringBuffer( 128 );
307 0 : buf.append( "COMMENT ON COLUMN " );
308 : bufferQuoteQualifiedIdentifier(
309 0 : buf, schema, name, extractStringProperty( column, st.NAME ), m_pSettings );
310 0 : buf.append( "IS " );
311 0 : bufferQuoteConstant( buf, description, m_pSettings );
312 0 : transaction.executeUpdate( buf.makeStringAndClear() );
313 : }
314 0 : }
315 0 : }
316 : }
317 :
318 0 : transaction.commit();
319 :
320 0 : disposeNoThrow( stmt );
321 : // TODO: cheaper recalculate
322 : // Container::append( concatQualified( schema, name ), descriptor ); // maintain the lists
323 0 : refresh();
324 0 : }
325 :
326 0 : void Tables::dropByIndex( sal_Int32 index )
327 : throw (::com::sun::star::sdbc::SQLException,
328 : ::com::sun::star::lang::IndexOutOfBoundsException,
329 : ::com::sun::star::uno::RuntimeException, std::exception)
330 : {
331 0 : osl::MutexGuard guard( m_refMutex->mutex );
332 0 : if( index < 0 || index >= m_values.getLength() )
333 : {
334 0 : OUStringBuffer buf( 128 );
335 0 : buf.append( "TABLES: Index out of range (allowed 0 to " + OUString::number(m_values.getLength() -1) +
336 0 : ", got " + OUString::number( index ) + ")" );
337 0 : throw com::sun::star::lang::IndexOutOfBoundsException( buf.makeStringAndClear(), *this );
338 : }
339 :
340 0 : Reference< XPropertySet > set;
341 0 : m_values[index] >>= set;
342 0 : Statics &st = getStatics();
343 0 : OUString name,schema;
344 0 : set->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
345 0 : set->getPropertyValue( st.NAME ) >>= name;
346 0 : if( extractStringProperty( set, st.TYPE ).equals( st.VIEW ) && m_pSettings->views.is() )
347 : {
348 0 : m_pSettings->pViewsImpl->dropByName( concatQualified( schema, name ) );
349 : }
350 : else
351 : {
352 0 : OUStringBuffer update( 128 );
353 0 : update.append( "DROP " );
354 0 : if( extractStringProperty( set, st.TYPE ).equals( st.VIEW ) )
355 0 : update.append( "VIEW " );
356 : else
357 0 : update.append( "TABLE " );
358 0 : bufferQuoteQualifiedIdentifier( update, schema, name, m_pSettings );
359 0 : Reference< XStatement > stmt = m_origin->createStatement( );
360 0 : DisposeGuard dispGuard( stmt );
361 0 : stmt->executeUpdate( update.makeStringAndClear() );
362 : }
363 :
364 0 : Container::dropByIndex( index );
365 0 : }
366 :
367 :
368 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > Tables::createDataDescriptor()
369 : throw (::com::sun::star::uno::RuntimeException, std::exception)
370 : {
371 0 : return new TableDescriptor( m_refMutex, m_origin, m_pSettings );
372 : }
373 :
374 0 : Reference< com::sun::star::container::XNameAccess > Tables::create(
375 : const ::rtl::Reference< RefCountedMutex > & refMutex,
376 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
377 : ConnectionSettings *pSettings,
378 : Tables **ppTables)
379 : {
380 0 : *ppTables = new Tables( refMutex, origin, pSettings );
381 0 : Reference< com::sun::star::container::XNameAccess > ret = *ppTables;
382 0 : (*ppTables)->refresh();
383 :
384 0 : return ret;
385 : }
386 :
387 0 : void Tables::disposing()
388 : {
389 0 : Container::disposing();
390 0 : }
391 :
392 : };
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|