1 /*************************************************************************
3 * $RCSfile: pq_xkeys.cxx,v $
7 * last change: $Author: jbu $ $Date: 2004/08/29 08:33:32 $
9 * The Contents of this file are made available subject to the terms of
10 * either of the following licenses
12 * - GNU Lesser General Public License Version 2.1
13 * - Sun Industry Standards Source License Version 1.1
15 * Sun Microsystems Inc., October, 2000
17 * GNU Lesser General Public License Version 2.1
18 * =============================================
19 * Copyright 2000 by Sun Microsystems, Inc.
20 * 901 San Antonio Road, Palo Alto, CA 94303, USA
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License version 2.1, as published by the Free Software Foundation.
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
37 * Sun Industry Standards Source License Version 1.1
38 * =================================================
39 * The contents of this file are subject to the Sun Industry Standards
40 * Source License Version 1.1 (the "License"); You may not use this file
41 * except in compliance with the License. You may obtain a copy of the
42 * License at http://www.openoffice.org/license.html.
44 * Software provided under this License is provided on an "AS IS" basis,
45 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
46 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
47 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
48 * See the License for the specific provisions governing your rights and
49 * obligations concerning the Software.
51 * The Initial Developer of the Original Code is: Joerg Budischewski
53 * Copyright: 2000 by Sun Microsystems, Inc.
55 * All Rights Reserved.
57 * Contributor(s): Joerg Budischewski
60 ************************************************************************/
65 #include <rtl/ustrbuf.hxx>
66 #include <rtl/strbuf.hxx>
68 #include <com/sun/star/sdbc/XRow.hpp>
69 #include <com/sun/star/sdbc/XParameters.hpp>
70 #include <com/sun/star/sdbc/KeyRule.hpp>
71 #include <com/sun/star/sdbcx/KeyType.hpp>
73 #include "pq_xkeys.hxx"
74 #include "pq_xkey.hxx"
75 #include "pq_statics.hxx"
76 #include "pq_tools.hxx"
78 using osl::MutexGuard
;
81 using rtl::OUStringBuffer
;
82 using rtl::OUStringToOString
;
84 using com::sun::star::beans::XPropertySet
;
86 using com::sun::star::uno::Any
;
87 using com::sun::star::uno::makeAny
;
88 using com::sun::star::uno::UNO_QUERY
;
89 using com::sun::star::uno::Type
;
90 using com::sun::star::uno::XInterface
;
91 using com::sun::star::uno::Reference
;
92 using com::sun::star::uno::Sequence
;
93 using com::sun::star::uno::RuntimeException
;
95 using com::sun::star::container::NoSuchElementException
;
96 using com::sun::star::lang::WrappedTargetException
;
98 using com::sun::star::sdbc::XRow
;
99 using com::sun::star::sdbc::XCloseable
;
100 using com::sun::star::sdbc::XStatement
;
101 using com::sun::star::sdbc::XResultSet
;
102 using com::sun::star::sdbc::XParameters
;
103 using com::sun::star::sdbc::XPreparedStatement
;
104 using com::sun::star::sdbc::XDatabaseMetaData
;
106 namespace pq_sdbc_driver
108 #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
111 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
112 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
113 ConnectionSettings
*pSettings
,
114 const rtl::OUString
&schemaName
,
115 const rtl::OUString
&tableName
)
116 : Container( refMutex
, origin
, pSettings
, getStatics().KEY
),
117 m_schemaName( schemaName
),
118 m_tableName( tableName
)
124 static sal_Int32
string2keytype( const rtl::OUString
&type
)
126 sal_Int32 ret
= com::sun::star::sdbcx::KeyType::UNIQUE
;
127 if( type
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "p" ) ) == 0 )
128 ret
= com::sun::star::sdbcx::KeyType::PRIMARY
;
129 else if( type
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "f" ) ) == 0 )
130 ret
= com::sun::star::sdbcx::KeyType::FOREIGN
;
134 static sal_Int32
string2keyrule( const rtl::OUString
& rule
)
136 sal_Int32 ret
= com::sun::star::sdbc::KeyRule::NO_ACTION
;
137 if( rule
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "r" ) ) == 0 )
138 ret
= com::sun::star::sdbc::KeyRule::RESTRICT
;
139 else if( rule
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "c" ) ) == 0 )
140 ret
= com::sun::star::sdbc::KeyRule::CASCADE
;
141 else if( rule
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "n" ) ) == 0 )
142 ret
= com::sun::star::sdbc::KeyRule::SET_NULL
;
143 else if( rule
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "d" ) ) == 0 )
144 ret
= com::sun::star::sdbc::KeyRule::SET_DEFAULT
;
150 // static void fillAttnum2attnameMap(
151 // Int2StringMap &map,
152 // const Reference< com::sun::star::sdbc::XConnection > &conn,
153 // const rtl::OUString &schema,
154 // const rtl::OUString &table )
156 // Reference< XPreparedStatement > prep = conn->prepareStatement(
157 // ASCII_STR( "SELECT attname,attnum "
158 // "FROM pg_attribute "
159 // "INNER JOIN pg_class ON attrelid = pg_class.oid "
160 // "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
161 // "WHERE relname=? AND nspname=?" ) );
163 // Reference< XParameters > paras( prep, UNO_QUERY );
164 // paras->setString( 1 , table );
165 // paras->setString( 2 , schema );
166 // Reference< XResultSet > rs = prep->executeQuery();
168 // Reference< XRow > xRow( rs , UNO_QUERY );
169 // while( rs->next() )
171 // map[ xRow->getInt(2) ] = xRow->getString(1);
175 // static Sequence< rtl::OUString > resolveColumnNames(
176 // const Int2StringMap &map, const rtl::OUString &array )
178 // Sequence< sal_Int32 > intArray = string2intarray( array );
179 // Sequence< ::rtl::OUString > ret( intArray.getLength() );
180 // for( int i = 0; i < intArray.getLength() ; i ++ )
182 // Int2StringMap::const_iterator ii = map.find( intArray[i] );
183 // if( ii != map.end() )
184 // ret[i] = ii->second;
190 throw (::com::sun::star::uno::RuntimeException
)
194 if( isLog( m_pSettings
, LogLevel::INFO
) )
196 rtl::OStringBuffer buf
;
197 buf
.append( "sdbcx.Keys get refreshed for table " );
198 buf
.append( OUStringToOString( m_schemaName
, m_pSettings
->encoding
) );
200 buf
.append( OUStringToOString( m_tableName
,m_pSettings
->encoding
) );
201 log( m_pSettings
, LogLevel::INFO
, buf
.makeStringAndClear().getStr() );
204 osl::MutexGuard
guard( m_refMutex
->mutex
);
205 Statics
& st
= getStatics();
207 Int2StringMap mainMap
;
208 fillAttnum2attnameMap( mainMap
, m_origin
, m_schemaName
, m_tableName
);
210 Reference
< XPreparedStatement
> stmt
= m_origin
->prepareStatement(
212 "SELECT conname, " // 1
216 "class2.relname, " // 5
217 "nmsp2.nspname, " // 6
220 "FROM pg_constraint INNER JOIN pg_class ON conrelid = pg_class.oid "
221 "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
222 "LEFT JOIN pg_class AS class2 ON confrelid = class2.oid "
223 "LEFT JOIN pg_namespace AS nmsp2 ON class2.relnamespace=nmsp2.oid "
224 "WHERE pg_class.relname = ? AND pg_namespace.nspname = ?" ) );
226 Reference
< XParameters
> paras( stmt
, UNO_QUERY
);
227 paras
->setString( 1 , m_tableName
);
228 paras
->setString( 2 , m_schemaName
);
229 Reference
< XResultSet
> rs
= stmt
->executeQuery();
231 Reference
< XRow
> xRow( rs
, UNO_QUERY
);
234 std::vector
< Any
, Allocator
< Any
> > vec
;
235 sal_Int32 keyIndex
= 0;
239 new Key( m_refMutex
, m_origin
, m_pSettings
, m_schemaName
, m_tableName
);
240 Reference
< com::sun::star::beans::XPropertySet
> prop
= pKey
;
242 pKey
->setPropertyValue_NoBroadcast_public(
243 st
.NAME
, makeAny( xRow
->getString( 1 ) ) );
244 sal_Int32 keyType
= string2keytype( xRow
->getString(2) );
245 pKey
->setPropertyValue_NoBroadcast_public( st
.TYPE
, makeAny( keyType
) );
246 pKey
->setPropertyValue_NoBroadcast_public(
247 st
.UPDATE_RULE
, makeAny( string2keyrule( xRow
->getString(3) ) ) );
248 pKey
->setPropertyValue_NoBroadcast_public(
249 st
.DELETE_RULE
, makeAny( string2keyrule( xRow
->getString(4) ) ) );
250 pKey
->setPropertyValue_NoBroadcast_public(
253 convertMappedIntArray2StringArray(
255 string2intarray( xRow
->getString( 7 ) ) ) ) );
257 if( com::sun::star::sdbcx::KeyType::FOREIGN
== keyType
)
259 OUStringBuffer
buf( 128 );
260 buf
.append( xRow
->getString( 6 ) );
261 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "." ) );
262 buf
.append( xRow
->getString( 5 ) );
263 pKey
->setPropertyValue_NoBroadcast_public(
264 st
.REFERENCED_TABLE
, makeAny( buf
.makeStringAndClear() ) );
266 Int2StringMap foreignMap
;
267 fillAttnum2attnameMap( foreignMap
, m_origin
, xRow
->getString(6), xRow
->getString(5));
268 pKey
->setPropertyValue_NoBroadcast_public(
269 st
.PRIVATE_FOREIGN_COLUMNS
,
271 convertMappedIntArray2StringArray(
273 string2intarray( xRow
->getString(8) ) ) ) );
276 vec
.push_back( makeAny( prop
) );
277 map
[ xRow
->getString( 1 ) ] = keyIndex
;
280 m_values
= Sequence
< com::sun::star::uno::Any
> ( & vec
[0] , vec
.size() );
281 m_name2index
.swap( map
);
283 catch ( com::sun::star::sdbc::SQLException
& e
)
285 throw RuntimeException( e
.Message
, e
.Context
);
288 fire( RefreshedBroadcaster( *this ) );
292 void Keys::appendByDescriptor(
293 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
>& descriptor
)
294 throw (::com::sun::star::sdbc::SQLException
,
295 ::com::sun::star::container::ElementExistException
,
296 ::com::sun::star::uno::RuntimeException
)
298 osl::MutexGuard
guard( m_refMutex
->mutex
);
300 OUStringBuffer
buf( 128 );
301 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE " ) );
302 bufferQuoteQualifiedIdentifier( buf
, m_schemaName
, m_tableName
);
303 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ADD " ) );
304 bufferKey2TableConstraint( buf
, descriptor
);
306 Reference
< XStatement
> stmt
=
307 m_origin
->createStatement();
308 stmt
->executeUpdate( buf
.makeStringAndClear() );
312 void Keys::dropByIndex( sal_Int32 index
)
313 throw (::com::sun::star::sdbc::SQLException
,
314 ::com::sun::star::lang::IndexOutOfBoundsException
,
315 ::com::sun::star::uno::RuntimeException
)
317 osl::MutexGuard
guard( m_refMutex
->mutex
);
318 if( index
< 0 || index
>= m_values
.getLength() )
320 OUStringBuffer
buf( 128 );
321 buf
.appendAscii( "TABLES: Index out of range (allowed 0 to " );
322 buf
.append( (sal_Int32
)(m_values
.getLength() -1) );
323 buf
.appendAscii( ", got " );
325 buf
.appendAscii( ")" );
326 throw com::sun::star::lang::IndexOutOfBoundsException(
327 buf
.makeStringAndClear(), *this );
331 Reference
< XPropertySet
> set
;
332 m_values
[index
] >>= set
;
334 OUStringBuffer
buf( 128 );
335 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ALTER TABLE " ) );
336 bufferQuoteQualifiedIdentifier( buf
, m_schemaName
, m_tableName
);
337 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM( " DROP CONSTRAINT " ) );
338 bufferQuoteIdentifier( buf
, extractStringProperty( set
, getStatics().NAME
) );
339 m_origin
->createStatement()->executeUpdate( buf
.makeStringAndClear() );
342 Container::dropByIndex( index
);
346 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> Keys::createDataDescriptor()
347 throw (::com::sun::star::uno::RuntimeException
)
349 return new KeyDescriptor( m_refMutex
, m_origin
, m_pSettings
);
352 Reference
< com::sun::star::container::XIndexAccess
> Keys::create(
353 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
354 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
355 ConnectionSettings
*pSettings
,
356 const rtl::OUString
& schemaName
,
357 const rtl::OUString
& tableName
)
359 Keys
*pKeys
= new Keys( refMutex
, origin
, pSettings
, schemaName
, tableName
);
360 Reference
< com::sun::star::container::XIndexAccess
> ret
= pKeys
;
365 //_________________________________________________________________________________________
366 KeyDescriptors::KeyDescriptors(
367 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
368 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
369 ConnectionSettings
*pSettings
)
370 : Container( refMutex
, origin
, pSettings
, getStatics().KEY
)
373 Reference
< com::sun::star::container::XIndexAccess
> KeyDescriptors::create(
374 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
375 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
376 ConnectionSettings
*pSettings
)
378 return new KeyDescriptors( refMutex
, origin
, pSettings
);
381 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> KeyDescriptors::createDataDescriptor()
382 throw (::com::sun::star::uno::RuntimeException
)
384 return new KeyDescriptor( m_refMutex
, m_origin
, m_pSettings
);