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/KeyRule.hpp>
64 : #include <com/sun/star/sdbcx/KeyType.hpp>
65 :
66 : #include "pq_xindexes.hxx"
67 : #include "pq_xindex.hxx"
68 : #include "pq_statics.hxx"
69 : #include "pq_tools.hxx"
70 :
71 : using osl::MutexGuard;
72 :
73 : using rtl::OUString;
74 : using rtl::OUStringBuffer;
75 : using rtl::OUStringToOString;
76 :
77 : using com::sun::star::beans::XPropertySet;
78 :
79 : using com::sun::star::uno::Any;
80 : using com::sun::star::uno::makeAny;
81 : using com::sun::star::uno::UNO_QUERY;
82 : using com::sun::star::uno::Type;
83 : using com::sun::star::uno::XInterface;
84 : using com::sun::star::uno::Reference;
85 : using com::sun::star::uno::Sequence;
86 : using com::sun::star::uno::RuntimeException;
87 :
88 : using com::sun::star::container::NoSuchElementException;
89 : using com::sun::star::container::XEnumerationAccess;
90 : using com::sun::star::container::XEnumeration;
91 :
92 : using com::sun::star::lang::WrappedTargetException;
93 :
94 : using com::sun::star::sdbcx::XColumnsSupplier;
95 :
96 : using com::sun::star::sdbc::XRow;
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 :
104 : namespace pq_sdbc_driver
105 : {
106 : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
107 :
108 0 : Indexes::Indexes(
109 : const ::rtl::Reference< RefCountedMutex > & refMutex,
110 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
111 : ConnectionSettings *pSettings,
112 : const rtl::OUString &schemaName,
113 : const rtl::OUString &tableName)
114 0 : : Container( refMutex, origin, pSettings, getStatics().KEY ),
115 : m_schemaName( schemaName ),
116 0 : m_tableName( tableName )
117 : {
118 0 : }
119 :
120 0 : Indexes::~Indexes()
121 0 : {}
122 :
123 0 : void Indexes::refresh()
124 : throw (::com::sun::star::uno::RuntimeException)
125 : {
126 : try
127 : {
128 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
129 : {
130 0 : rtl::OStringBuffer buf;
131 0 : buf.append( "sdbcx.Indexes get refreshed for table " );
132 0 : buf.append( OUStringToOString( m_schemaName, m_pSettings->encoding ) );
133 0 : buf.append( "." );
134 0 : buf.append( OUStringToOString( m_tableName,m_pSettings->encoding ) );
135 0 : log( m_pSettings, LogLevel::INFO, buf.makeStringAndClear().getStr() );
136 : }
137 :
138 0 : osl::MutexGuard guard( m_refMutex->mutex );
139 0 : Statics & st = getStatics();
140 :
141 0 : Int2StringMap column2NameMap;
142 0 : fillAttnum2attnameMap( column2NameMap, m_origin, m_schemaName, m_tableName );
143 :
144 : // see XDatabaseMetaData::getIndexInfo()
145 0 : Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
146 : ASCII_STR(
147 : "SELECT nspname, " // 1
148 : "pg_class.relname, " // 2
149 : "class2.relname, " // 3
150 : "indisclustered, " // 4
151 : "indisunique, " // 5
152 : "indisprimary, " // 6
153 : "indkey " // 7
154 : "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
155 : "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
156 : "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
157 0 : "WHERE nspname = ? AND pg_class.relname = ?" ) );
158 :
159 0 : Reference< XParameters > params( stmt, UNO_QUERY);
160 0 : params->setString( 1, m_schemaName );
161 0 : params->setString( 2, m_tableName );
162 0 : Reference< XResultSet > rs = stmt->executeQuery();
163 :
164 0 : Reference< XRow > row( rs, UNO_QUERY );
165 0 : String2IntMap map;
166 0 : m_values = Sequence< com::sun::star::uno::Any > ();
167 0 : sal_Int32 index = 0;
168 0 : while( rs->next() )
169 : {
170 : static const sal_Int32 C_SCHEMA = 1;
171 : static const sal_Int32 C_TABLENAME = 2;
172 : static const sal_Int32 C_INDEXNAME = 3;
173 : static const sal_Int32 C_IS_CLUSTERED = 4;
174 : static const sal_Int32 C_IS_UNIQUE = 5;
175 : static const sal_Int32 C_IS_PRIMARY = 6;
176 : static const sal_Int32 C_COLUMNS = 7;
177 0 : OUString currentIndexName = row->getString( C_INDEXNAME );
178 : Index *pIndex =
179 : new Index( m_refMutex, m_origin, m_pSettings,
180 0 : m_schemaName, m_tableName );
181 :
182 : (void) C_SCHEMA; (void) C_TABLENAME;
183 0 : sal_Bool isUnique = row->getBoolean( C_IS_UNIQUE );
184 0 : sal_Bool isPrimary = row->getBoolean( C_IS_PRIMARY );
185 0 : sal_Bool isClusterd = row->getBoolean( C_IS_CLUSTERED );
186 0 : Reference< com::sun::star::beans::XPropertySet > prop = pIndex;
187 : pIndex->setPropertyValue_NoBroadcast_public(
188 0 : st.IS_UNIQUE, Any( &isUnique, getBooleanCppuType() ) );
189 : pIndex->setPropertyValue_NoBroadcast_public(
190 0 : st.IS_PRIMARY_KEY_INDEX, Any( &isPrimary, getBooleanCppuType() ) );
191 : pIndex->setPropertyValue_NoBroadcast_public(
192 0 : st.IS_CLUSTERED, Any( &isClusterd, getBooleanCppuType() ) );
193 : pIndex->setPropertyValue_NoBroadcast_public(
194 0 : st.NAME, makeAny( currentIndexName ) );
195 :
196 0 : Sequence< sal_Int32 > seq = parseIntArray( row->getString( C_COLUMNS ) );
197 0 : Sequence< OUString > columnNames(seq.getLength());
198 0 : for( int columns = 0 ; columns < seq.getLength() ; columns ++ )
199 : {
200 0 : columnNames[columns] = column2NameMap[ seq[columns] ];
201 : }
202 :
203 : pIndex->setPropertyValue_NoBroadcast_public(
204 0 : st.PRIVATE_COLUMN_INDEXES, makeAny( columnNames ));
205 :
206 : {
207 0 : const int currentIndex = index++;
208 : assert(currentIndex == m_values.getLength());
209 0 : m_values.realloc( index );
210 0 : m_values[currentIndex] = makeAny( prop );
211 0 : map[ currentIndexName ] = currentIndex;
212 : }
213 0 : }
214 0 : m_name2index.swap( map );
215 : }
216 0 : catch ( com::sun::star::sdbc::SQLException & e )
217 : {
218 0 : throw RuntimeException( e.Message , e.Context );
219 : }
220 :
221 0 : fire( RefreshedBroadcaster( *this ) );
222 0 : }
223 :
224 :
225 0 : void Indexes::appendByDescriptor(
226 : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
227 : throw (::com::sun::star::sdbc::SQLException,
228 : ::com::sun::star::container::ElementExistException,
229 : ::com::sun::star::uno::RuntimeException)
230 : {
231 0 : Statics & st = getStatics();
232 0 : OUString name = extractStringProperty( descriptor, st.NAME );
233 :
234 0 : sal_Bool isUnique = extractBoolProperty( descriptor, st.IS_UNIQUE );
235 :
236 0 : OUStringBuffer buf( 128 );
237 :
238 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "CREATE " ) );
239 0 : if( isUnique )
240 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "UNIQUE " ) );
241 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "INDEX " ) );
242 0 : bufferQuoteIdentifier( buf, name, m_pSettings );
243 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ON " ) );
244 0 : bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
245 :
246 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ( " ) );
247 :
248 0 : Reference< XColumnsSupplier > columns( descriptor, UNO_QUERY );
249 0 : if( columns.is() )
250 : {
251 0 : Reference< XEnumerationAccess > access( columns->getColumns(), UNO_QUERY );
252 0 : if( access.is() )
253 : {
254 0 : Reference< XEnumeration > xEnum( access->createEnumeration() );
255 0 : bool first = true;
256 0 : while( xEnum.is() && xEnum->hasMoreElements() )
257 : {
258 0 : Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
259 0 : if( first )
260 : {
261 0 : first = false;
262 : }
263 : else
264 : {
265 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
266 : }
267 0 : buf.append( extractStringProperty( column, st.NAME ) );
268 0 : }
269 0 : }
270 : }
271 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ) " ) );
272 :
273 0 : m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
274 0 : refresh();
275 0 : }
276 :
277 0 : void Indexes::dropByIndex( sal_Int32 index )
278 : throw (::com::sun::star::sdbc::SQLException,
279 : ::com::sun::star::lang::IndexOutOfBoundsException,
280 : ::com::sun::star::uno::RuntimeException)
281 : {
282 :
283 :
284 0 : osl::MutexGuard guard( m_refMutex->mutex );
285 0 : if( index < 0 || index >= m_values.getLength() )
286 : {
287 0 : OUStringBuffer buf( 128 );
288 0 : buf.appendAscii( "Indexes: Index out of range (allowed 0 to " );
289 0 : buf.append( (sal_Int32) (m_values.getLength() -1) );
290 0 : buf.appendAscii( ", got " );
291 0 : buf.append( index );
292 0 : buf.appendAscii( ")" );
293 : throw com::sun::star::lang::IndexOutOfBoundsException(
294 0 : buf.makeStringAndClear(), *this );
295 : }
296 :
297 0 : Reference< XPropertySet > set;
298 0 : m_values[index] >>= set;
299 0 : Statics &st = getStatics();
300 :
301 0 : OUStringBuffer buf( 128 );
302 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "DROP INDEX " ) );
303 0 : bufferQuoteIdentifier( buf, extractStringProperty( set, st.NAME ), m_pSettings );
304 0 : m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
305 :
306 0 : Container::dropByIndex( index );
307 0 : }
308 :
309 :
310 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > Indexes::createDataDescriptor()
311 : throw (::com::sun::star::uno::RuntimeException)
312 : {
313 0 : return new IndexDescriptor( m_refMutex, m_origin, m_pSettings );
314 : }
315 :
316 0 : Reference< com::sun::star::container::XNameAccess > Indexes::create(
317 : const ::rtl::Reference< RefCountedMutex > & refMutex,
318 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
319 : ConnectionSettings *pSettings,
320 : const rtl::OUString & schemaName,
321 : const rtl::OUString & tableName)
322 : {
323 0 : Indexes *pIndexes = new Indexes( refMutex, origin, pSettings, schemaName, tableName );
324 0 : Reference< com::sun::star::container::XNameAccess > ret = pIndexes;
325 0 : pIndexes->refresh();
326 0 : return ret;
327 : }
328 :
329 :
330 : //_________________________________________________________________________________________
331 0 : IndexDescriptors::IndexDescriptors(
332 : const ::rtl::Reference< RefCountedMutex > & refMutex,
333 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
334 : ConnectionSettings *pSettings)
335 0 : : Container( refMutex, origin, pSettings, getStatics().INDEX )
336 0 : {}
337 :
338 0 : Reference< com::sun::star::container::XNameAccess > IndexDescriptors::create(
339 : const ::rtl::Reference< RefCountedMutex > & refMutex,
340 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
341 : ConnectionSettings *pSettings)
342 : {
343 0 : return new IndexDescriptors( refMutex, origin, pSettings );
344 : }
345 :
346 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > IndexDescriptors::createDataDescriptor()
347 : throw (::com::sun::star::uno::RuntimeException)
348 : {
349 0 : return new IndexDescriptor( m_refMutex, m_origin, m_pSettings );
350 : }
351 :
352 : };
|