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 : #include <rtl/strbuf.hxx>
39 :
40 : #include <com/sun/star/sdbc/XRow.hpp>
41 : #include <com/sun/star/sdbc/XParameters.hpp>
42 : #include <com/sun/star/sdbc/KeyRule.hpp>
43 : #include <com/sun/star/sdbcx/KeyType.hpp>
44 :
45 : #include "pq_xkeys.hxx"
46 : #include "pq_xkey.hxx"
47 : #include "pq_statics.hxx"
48 : #include "pq_tools.hxx"
49 :
50 : using osl::MutexGuard;
51 :
52 :
53 : using com::sun::star::beans::XPropertySet;
54 :
55 : using com::sun::star::uno::Any;
56 : using com::sun::star::uno::makeAny;
57 : using com::sun::star::uno::UNO_QUERY;
58 : using com::sun::star::uno::Type;
59 : using com::sun::star::uno::XInterface;
60 : using com::sun::star::uno::Reference;
61 : using com::sun::star::uno::Sequence;
62 : using com::sun::star::uno::RuntimeException;
63 :
64 : using com::sun::star::container::NoSuchElementException;
65 : using com::sun::star::lang::WrappedTargetException;
66 :
67 : using com::sun::star::sdbc::XRow;
68 : using com::sun::star::sdbc::XCloseable;
69 : using com::sun::star::sdbc::XStatement;
70 : using com::sun::star::sdbc::XResultSet;
71 : using com::sun::star::sdbc::XParameters;
72 : using com::sun::star::sdbc::XPreparedStatement;
73 : using com::sun::star::sdbc::XDatabaseMetaData;
74 :
75 : namespace pq_sdbc_driver
76 : {
77 :
78 0 : Keys::Keys(
79 : const ::rtl::Reference< RefCountedMutex > & refMutex,
80 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
81 : ConnectionSettings *pSettings,
82 : const OUString &schemaName,
83 : const OUString &tableName)
84 0 : : Container( refMutex, origin, pSettings, getStatics().KEY ),
85 : m_schemaName( schemaName ),
86 0 : m_tableName( tableName )
87 0 : {}
88 :
89 0 : Keys::~Keys()
90 0 : {}
91 :
92 0 : static sal_Int32 string2keytype( const OUString &type )
93 : {
94 0 : sal_Int32 ret = com::sun::star::sdbcx::KeyType::UNIQUE;
95 0 : if ( type == "p" )
96 0 : ret = com::sun::star::sdbcx::KeyType::PRIMARY;
97 0 : else if ( type == "f" )
98 0 : ret = com::sun::star::sdbcx::KeyType::FOREIGN;
99 0 : return ret;
100 : }
101 :
102 0 : static sal_Int32 string2keyrule( const OUString & rule )
103 : {
104 0 : sal_Int32 ret = com::sun::star::sdbc::KeyRule::NO_ACTION;
105 0 : if( rule == "r" )
106 0 : ret = com::sun::star::sdbc::KeyRule::RESTRICT;
107 0 : else if( rule == "c" )
108 0 : ret = com::sun::star::sdbc::KeyRule::CASCADE;
109 0 : else if( rule == "n" )
110 0 : ret = com::sun::star::sdbc::KeyRule::SET_NULL;
111 0 : else if( rule == "d" )
112 0 : ret = com::sun::star::sdbc::KeyRule::SET_DEFAULT;
113 0 : return ret;
114 : }
115 :
116 0 : void Keys::refresh()
117 : throw (::com::sun::star::uno::RuntimeException, std::exception)
118 : {
119 : try
120 : {
121 0 : if( isLog( m_pSettings, LogLevel::INFO ) )
122 : {
123 0 : OString buf( "sdbcx.Keys get refreshed for table " +
124 0 : OUStringToOString( m_schemaName, m_pSettings->encoding ) +
125 0 : "." + OUStringToOString( m_tableName,m_pSettings->encoding ));
126 0 : log( m_pSettings, LogLevel::INFO, buf.getStr() );
127 : }
128 :
129 0 : osl::MutexGuard guard( m_refMutex->mutex );
130 0 : Statics & st = getStatics();
131 :
132 0 : Int2StringMap mainMap;
133 0 : fillAttnum2attnameMap( mainMap, m_origin, m_schemaName, m_tableName );
134 :
135 0 : Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
136 : "SELECT conname, " // 1
137 : "contype, " // 2
138 : "confupdtype, " // 3
139 : "confdeltype, " // 4
140 : "class2.relname, " // 5
141 : "nmsp2.nspname, " // 6
142 : "conkey," // 7
143 : "confkey " // 8
144 : "FROM pg_constraint INNER JOIN pg_class ON conrelid = pg_class.oid "
145 : "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
146 : "LEFT JOIN pg_class AS class2 ON confrelid = class2.oid "
147 : "LEFT JOIN pg_namespace AS nmsp2 ON class2.relnamespace=nmsp2.oid "
148 0 : "WHERE pg_class.relname = ? AND pg_namespace.nspname = ?" );
149 :
150 0 : Reference< XParameters > paras( stmt, UNO_QUERY );
151 0 : paras->setString( 1 , m_tableName );
152 0 : paras->setString( 2 , m_schemaName );
153 0 : Reference< XResultSet > rs = stmt->executeQuery();
154 :
155 0 : Reference< XRow > xRow( rs , UNO_QUERY );
156 :
157 0 : String2IntMap map;
158 0 : m_values = Sequence< com::sun::star::uno::Any > ();
159 0 : int keyIndex = 0;
160 0 : while( rs->next() )
161 : {
162 : Key * pKey =
163 0 : new Key( m_refMutex, m_origin, m_pSettings , m_schemaName, m_tableName );
164 0 : Reference< com::sun::star::beans::XPropertySet > prop = pKey;
165 :
166 : pKey->setPropertyValue_NoBroadcast_public(
167 0 : st.NAME, makeAny( xRow->getString( 1 ) ) );
168 0 : sal_Int32 keyType = string2keytype( xRow->getString(2) );
169 0 : pKey->setPropertyValue_NoBroadcast_public( st.TYPE, makeAny( keyType ) );
170 : pKey->setPropertyValue_NoBroadcast_public(
171 0 : st.UPDATE_RULE, makeAny( string2keyrule( xRow->getString(3) ) ) );
172 : pKey->setPropertyValue_NoBroadcast_public(
173 0 : st.DELETE_RULE, makeAny( string2keyrule( xRow->getString(4) ) ) );
174 : pKey->setPropertyValue_NoBroadcast_public(
175 : st.PRIVATE_COLUMNS,
176 : makeAny(
177 : convertMappedIntArray2StringArray(
178 : mainMap,
179 0 : string2intarray( xRow->getString( 7 ) ) ) ) );
180 :
181 0 : if( com::sun::star::sdbcx::KeyType::FOREIGN == keyType )
182 : {
183 0 : OUStringBuffer buf( 128 );
184 0 : buf.append( xRow->getString( 6 ) + "." + xRow->getString( 5 ) );
185 : pKey->setPropertyValue_NoBroadcast_public(
186 0 : st.REFERENCED_TABLE, makeAny( buf.makeStringAndClear() ) );
187 :
188 0 : Int2StringMap foreignMap;
189 0 : fillAttnum2attnameMap( foreignMap, m_origin, xRow->getString(6), xRow->getString(5));
190 : pKey->setPropertyValue_NoBroadcast_public(
191 : st.PRIVATE_FOREIGN_COLUMNS,
192 : makeAny(
193 : convertMappedIntArray2StringArray(
194 : foreignMap,
195 0 : string2intarray( xRow->getString(8) ) ) ) );
196 : }
197 :
198 :
199 : {
200 0 : const int currentKeyIndex = keyIndex++;
201 0 : map[ xRow->getString( 1 ) ] = currentKeyIndex;
202 : assert(currentKeyIndex == m_values.getLength());
203 0 : m_values.realloc( keyIndex );
204 0 : m_values[currentKeyIndex] = makeAny( prop );
205 : }
206 0 : }
207 0 : m_name2index.swap( map );
208 : }
209 0 : catch ( com::sun::star::sdbc::SQLException & e )
210 : {
211 0 : throw RuntimeException( e.Message , e.Context );
212 : }
213 :
214 0 : fire( RefreshedBroadcaster( *this ) );
215 0 : }
216 :
217 :
218 0 : void Keys::appendByDescriptor(
219 : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
220 : throw (::com::sun::star::sdbc::SQLException,
221 : ::com::sun::star::container::ElementExistException,
222 : ::com::sun::star::uno::RuntimeException, std::exception)
223 : {
224 0 : osl::MutexGuard guard( m_refMutex->mutex );
225 :
226 0 : OUStringBuffer buf( 128 );
227 0 : buf.append( "ALTER TABLE " );
228 0 : bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
229 0 : buf.append( " ADD " );
230 0 : bufferKey2TableConstraint( buf, descriptor, m_pSettings );
231 :
232 : Reference< XStatement > stmt =
233 0 : m_origin->createStatement();
234 0 : stmt->executeUpdate( buf.makeStringAndClear() );
235 0 : }
236 :
237 :
238 0 : void Keys::dropByIndex( sal_Int32 index )
239 : throw (::com::sun::star::sdbc::SQLException,
240 : ::com::sun::star::lang::IndexOutOfBoundsException,
241 : ::com::sun::star::uno::RuntimeException, std::exception)
242 : {
243 0 : osl::MutexGuard guard( m_refMutex->mutex );
244 0 : if( index < 0 || index >= m_values.getLength() )
245 : {
246 0 : OUStringBuffer buf( 128 );
247 0 : buf.append( "TABLES: Index out of range (allowed 0 to " + OUString::number(m_values.getLength() -1) +
248 0 : ", got " + OUString::number( index ) + ")" );
249 : throw com::sun::star::lang::IndexOutOfBoundsException(
250 0 : buf.makeStringAndClear(), *this );
251 : }
252 :
253 :
254 0 : Reference< XPropertySet > set;
255 0 : m_values[index] >>= set;
256 :
257 0 : OUStringBuffer buf( 128 );
258 0 : buf.append( "ALTER TABLE " );
259 0 : bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
260 0 : buf.append( " DROP CONSTRAINT " );
261 0 : bufferQuoteIdentifier( buf, extractStringProperty( set , getStatics().NAME ), m_pSettings );
262 0 : m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
263 :
264 :
265 0 : Container::dropByIndex( index );
266 0 : }
267 :
268 :
269 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > Keys::createDataDescriptor()
270 : throw (::com::sun::star::uno::RuntimeException, std::exception)
271 : {
272 0 : return new KeyDescriptor( m_refMutex, m_origin, m_pSettings );
273 : }
274 :
275 0 : Reference< com::sun::star::container::XIndexAccess > Keys::create(
276 : const ::rtl::Reference< RefCountedMutex > & refMutex,
277 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
278 : ConnectionSettings *pSettings,
279 : const OUString & schemaName,
280 : const OUString & tableName)
281 : {
282 0 : Keys *pKeys = new Keys( refMutex, origin, pSettings, schemaName, tableName );
283 0 : Reference< com::sun::star::container::XIndexAccess > ret = pKeys;
284 0 : pKeys->refresh();
285 :
286 0 : return ret;
287 : }
288 :
289 0 : KeyDescriptors::KeyDescriptors(
290 : const ::rtl::Reference< RefCountedMutex > & refMutex,
291 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
292 : ConnectionSettings *pSettings)
293 0 : : Container( refMutex, origin, pSettings, getStatics().KEY )
294 0 : {}
295 :
296 0 : Reference< com::sun::star::container::XIndexAccess > KeyDescriptors::create(
297 : const ::rtl::Reference< RefCountedMutex > & refMutex,
298 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
299 : ConnectionSettings *pSettings)
300 : {
301 0 : return new KeyDescriptors( refMutex, origin, pSettings );
302 : }
303 :
304 0 : ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > KeyDescriptors::createDataDescriptor()
305 : throw (::com::sun::star::uno::RuntimeException, std::exception)
306 : {
307 0 : return new KeyDescriptor( m_refMutex, m_origin, m_pSettings );
308 : }
309 :
310 : };
311 :
312 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|