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