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 "pq_statement.hxx"
59 : : #include "pq_fakedupdateableresultset.hxx"
60 : : #include "pq_updateableresultset.hxx"
61 : : #include "pq_tools.hxx"
62 : : #include "pq_statics.hxx"
63 : :
64 : : #include <osl/thread.h>
65 : : #include <osl/time.h>
66 : :
67 : : #include <rtl/ustrbuf.hxx>
68 : : #include <rtl/strbuf.hxx>
69 : :
70 : : #include <cppuhelper/typeprovider.hxx>
71 : : #include <cppuhelper/queryinterface.hxx>
72 : :
73 : : #include <com/sun/star/beans/PropertyAttribute.hpp>
74 : :
75 : : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
76 : : #include <com/sun/star/sdbc/ResultSetType.hpp>
77 : : #include <com/sun/star/sdbc/XParameters.hpp>
78 : :
79 : : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
80 : : #include <com/sun/star/sdbcx/KeyType.hpp>
81 : : #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
82 : :
83 : : #include <com/sun/star/container/XIndexAccess.hpp>
84 : : #include <com/sun/star/container/XEnumerationAccess.hpp>
85 : :
86 : : #include <string.h>
87 : :
88 : : using osl::Mutex;
89 : : using osl::MutexGuard;
90 : :
91 : : using rtl::OUString;
92 : : using rtl::OUStringBuffer;
93 : : using rtl::OUStringToOString;
94 : : using rtl::OStringToOUString;
95 : : using rtl::OString;
96 : :
97 : : using com::sun::star::uno::Any;
98 : : using com::sun::star::uno::makeAny;
99 : : using com::sun::star::uno::Type;
100 : : using com::sun::star::uno::RuntimeException;
101 : : using com::sun::star::uno::Exception;
102 : : using com::sun::star::uno::Sequence;
103 : : using com::sun::star::uno::Reference;
104 : : using com::sun::star::uno::XInterface;
105 : : using com::sun::star::uno::UNO_QUERY;
106 : :
107 : : using com::sun::star::lang::IllegalArgumentException;
108 : :
109 : : using com::sun::star::sdbc::XWarningsSupplier;
110 : : using com::sun::star::sdbc::XCloseable;
111 : : using com::sun::star::sdbc::XStatement;
112 : : using com::sun::star::sdbc::XPreparedStatement;
113 : : using com::sun::star::sdbc::XParameters;
114 : : using com::sun::star::sdbc::XRow;
115 : : using com::sun::star::sdbc::XResultSet;
116 : : using com::sun::star::sdbc::XGeneratedResultSet;
117 : : using com::sun::star::sdbc::XConnection;
118 : : using com::sun::star::sdbc::SQLException;
119 : :
120 : : using com::sun::star::sdbcx::XColumnsSupplier;
121 : : using com::sun::star::sdbcx::XTablesSupplier;
122 : : using com::sun::star::sdbcx::XKeysSupplier;
123 : :
124 : : using com::sun::star::beans::Property;
125 : : using com::sun::star::beans::XPropertySetInfo;
126 : : using com::sun::star::beans::XPropertySet;
127 : : using com::sun::star::beans::XFastPropertySet;
128 : : using com::sun::star::beans::XMultiPropertySet;
129 : :
130 : : using com::sun::star::container::XNameAccess;
131 : : using com::sun::star::container::XEnumerationAccess;
132 : : using com::sun::star::container::XEnumeration;
133 : : using com::sun::star::container::XIndexAccess;
134 : :
135 : : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
136 : : namespace pq_sdbc_driver
137 : : {
138 : 0 : static ::cppu::IPropertyArrayHelper & getStatementPropertyArrayHelper()
139 : : {
140 : : static ::cppu::IPropertyArrayHelper *pArrayHelper;
141 : 0 : if( ! pArrayHelper )
142 : : {
143 : 0 : MutexGuard guard( Mutex::getGlobalMutex() );
144 : 0 : if( ! pArrayHelper )
145 : : {
146 : : static Property aTable[] =
147 : : {
148 : : Property(
149 : : OUString( RTL_CONSTASCII_USTRINGPARAM("CursorName") ), 0,
150 : 0 : ::getCppuType( (OUString *)0) , 0 ),
151 : : Property(
152 : : OUString( RTL_CONSTASCII_USTRINGPARAM("EscapeProcessing") ), 1,
153 : 0 : ::getBooleanCppuType() , 0 ),
154 : : Property(
155 : : OUString( RTL_CONSTASCII_USTRINGPARAM("FetchDirection") ), 2,
156 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
157 : : Property(
158 : : OUString( RTL_CONSTASCII_USTRINGPARAM("FetchSize") ), 3,
159 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
160 : : Property(
161 : : OUString( RTL_CONSTASCII_USTRINGPARAM("MaxFieldSize") ), 4,
162 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
163 : : Property(
164 : : OUString( RTL_CONSTASCII_USTRINGPARAM("MaxRows") ), 5,
165 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
166 : : Property(
167 : : OUString( RTL_CONSTASCII_USTRINGPARAM("QueryTimeOut") ), 6,
168 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
169 : : Property(
170 : : OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetConcurrency") ), 7,
171 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 ),
172 : : Property(
173 : : OUString( RTL_CONSTASCII_USTRINGPARAM("ResultSetType") ), 8,
174 : 0 : ::getCppuType( (sal_Int32 *)0) , 0 )
175 : 0 : };
176 : : OSL_ASSERT( sizeof(aTable)/ sizeof(Property) == STATEMENT_SIZE );
177 : 0 : static ::cppu::OPropertyArrayHelper arrayHelper( aTable, STATEMENT_SIZE, sal_True );
178 : 0 : pArrayHelper = &arrayHelper;
179 : 0 : }
180 : : }
181 : 0 : return *pArrayHelper;
182 : : }
183 : :
184 : 0 : Statement::Statement( const ::rtl::Reference< RefCountedMutex > & refMutex,
185 : : const Reference< XConnection > & conn,
186 : : struct ConnectionSettings *pSettings )
187 : 0 : : OComponentHelper( refMutex->mutex ),
188 : : OPropertySetHelper( OComponentHelper::rBHelper ),
189 : : m_connection( conn ),
190 : : m_pSettings( pSettings ),
191 : : m_refMutex( refMutex ),
192 : 0 : m_lastOidInserted( InvalidOid )
193 : : {
194 : 0 : m_props[STATEMENT_QUERY_TIME_OUT] = makeAny( (sal_Int32)0 );
195 : 0 : m_props[STATEMENT_MAX_ROWS] = makeAny( (sal_Int32)0 );
196 : : m_props[STATEMENT_RESULT_SET_CONCURRENCY] = makeAny(
197 : 0 : com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY );
198 : : m_props[STATEMENT_RESULT_SET_TYPE] = makeAny(
199 : 0 : com::sun::star::sdbc::ResultSetType::SCROLL_INSENSITIVE );
200 : 0 : }
201 : :
202 : 0 : Statement::~Statement()
203 : : {
204 : : POSTGRE_TRACE( "dtor Statement" );
205 : 0 : }
206 : :
207 : 0 : void Statement::checkClosed() throw (SQLException, RuntimeException )
208 : : {
209 : 0 : if( ! m_pSettings || ! m_pSettings->pConnection )
210 : : throw SQLException(
211 : : ASCII_STR("pq_driver: Statement or connection has already been closed !" ),
212 : 0 : *this, OUString(),1,Any());
213 : 0 : }
214 : :
215 : 0 : Any Statement::queryInterface( const Type & reqType ) throw (RuntimeException)
216 : : {
217 : 0 : Any ret;
218 : :
219 : 0 : ret = OComponentHelper::queryInterface( reqType );
220 : 0 : if( ! ret.hasValue() )
221 : : ret = ::cppu::queryInterface( reqType,
222 : : static_cast< XWarningsSupplier * > ( this ),
223 : : static_cast< XStatement * > ( this ),
224 : : static_cast< com::sun::star::sdbc::XResultSetMetaDataSupplier * > ( this ),
225 : : static_cast< XCloseable * > ( this ),
226 : : static_cast< XPropertySet * > ( this ),
227 : : static_cast< XMultiPropertySet * > ( this ),
228 : : static_cast< XGeneratedResultSet * > ( this ),
229 : 0 : static_cast< XFastPropertySet * > ( this ) );
230 : 0 : return ret;
231 : : }
232 : :
233 : :
234 : 0 : Sequence< Type > Statement::getTypes() throw ( RuntimeException )
235 : : {
236 : : static cppu::OTypeCollection *pCollection;
237 : 0 : if( ! pCollection )
238 : : {
239 : 0 : MutexGuard guard( osl::Mutex::getGlobalMutex() );
240 : 0 : if( !pCollection )
241 : : {
242 : : static cppu::OTypeCollection collection(
243 : 0 : getCppuType( (Reference< XWarningsSupplier> *) 0 ),
244 : 0 : getCppuType( (Reference< XStatement> *) 0 ),
245 : 0 : getCppuType( (Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier> *) 0 ),
246 : 0 : getCppuType( (Reference< XCloseable> *) 0 ),
247 : 0 : getCppuType( (Reference< XPropertySet >*) 0 ),
248 : 0 : getCppuType( (Reference< XFastPropertySet > *) 0 ),
249 : 0 : getCppuType( (Reference< XMultiPropertySet > *) 0 ),
250 : 0 : getCppuType( (Reference< XGeneratedResultSet > *) 0 ),
251 : 0 : OComponentHelper::getTypes());
252 : 0 : pCollection = &collection;
253 : 0 : }
254 : : }
255 : 0 : return pCollection->getTypes();
256 : : }
257 : :
258 : 0 : Sequence< sal_Int8> Statement::getImplementationId() throw ( RuntimeException )
259 : : {
260 : : static cppu::OImplementationId *pId;
261 : 0 : if( ! pId )
262 : : {
263 : 0 : MutexGuard guard( osl::Mutex::getGlobalMutex() );
264 : 0 : if( ! pId )
265 : : {
266 : 0 : static cppu::OImplementationId id(sal_False);
267 : 0 : pId = &id;
268 : 0 : }
269 : : }
270 : 0 : return pId->getImplementationId();
271 : : }
272 : :
273 : 0 : void Statement::close( ) throw (SQLException, RuntimeException)
274 : : {
275 : : // let the connection die without acquired mutex !
276 : 0 : Reference< XConnection > r;
277 : 0 : Reference< XCloseable > resultSet;
278 : : {
279 : 0 : MutexGuard guard( m_refMutex->mutex );
280 : 0 : m_pSettings = 0;
281 : 0 : r = m_connection;
282 : 0 : m_connection.clear();
283 : :
284 : 0 : resultSet = m_lastResultset;
285 : 0 : m_lastResultset.clear();
286 : : }
287 : 0 : if( resultSet.is() )
288 : : {
289 : 0 : resultSet->close();
290 : : POSTGRE_TRACE( "statement closed" );
291 : 0 : }
292 : :
293 : 0 : }
294 : :
295 : 0 : void Statement::raiseSQLException(
296 : : const OUString & sql, const char * errorMsg, const char *errorType )
297 : : throw( SQLException )
298 : : {
299 : 0 : OUStringBuffer buf(128);
300 : 0 : buf.appendAscii( "pq_driver: ");
301 : 0 : if( errorType )
302 : : {
303 : 0 : buf.appendAscii( "[" );
304 : 0 : buf.appendAscii( errorType );
305 : 0 : buf.appendAscii( "]" );
306 : : }
307 : : buf.append(
308 : 0 : rtl::OUString( errorMsg, strlen(errorMsg) , m_pSettings->encoding ) );
309 : 0 : buf.appendAscii( " (caused by statement '" );
310 : 0 : buf.append( sql );
311 : 0 : buf.appendAscii( "')" );
312 : 0 : OUString error = buf.makeStringAndClear();
313 : 0 : log( m_pSettings, LogLevel::ERROR, error );
314 : 0 : throw SQLException( error, *this, OUString(), 1, Any() );
315 : : }
316 : :
317 : 0 : Reference< XResultSet > Statement::executeQuery(const OUString& sql )
318 : : throw (SQLException, RuntimeException)
319 : : {
320 : 0 : Reference< XCloseable > lastResultSetHolder = m_lastResultset;
321 : 0 : if( lastResultSetHolder.is() )
322 : 0 : lastResultSetHolder->close();
323 : :
324 : 0 : if( ! execute( sql ) )
325 : : {
326 : 0 : raiseSQLException( sql, "not a query" );
327 : : }
328 : 0 : return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
329 : : }
330 : :
331 : 0 : sal_Int32 Statement::executeUpdate( const OUString& sql )
332 : : throw (SQLException, RuntimeException)
333 : : {
334 : 0 : if( execute( sql ) )
335 : : {
336 : 0 : raiseSQLException( sql, "not a command" );
337 : : }
338 : 0 : return m_multipleResultUpdateCount;
339 : : }
340 : :
341 : :
342 : 0 : static void raiseSQLException(
343 : : ConnectionSettings *pSettings,
344 : : const Reference< XInterface> & owner,
345 : : const OString & sql,
346 : : const char * errorMsg,
347 : : const char *errorType = 0 )
348 : : throw( SQLException )
349 : : {
350 : 0 : OUStringBuffer buf(128);
351 : 0 : buf.appendAscii( "pq_driver: ");
352 : 0 : if( errorType )
353 : : {
354 : 0 : buf.appendAscii( "[" );
355 : 0 : buf.appendAscii( errorType );
356 : 0 : buf.appendAscii( "]" );
357 : : }
358 : : buf.append(
359 : 0 : rtl::OUString( errorMsg, strlen(errorMsg) , pSettings->encoding ) );
360 : 0 : buf.appendAscii( " (caused by statement '" );
361 : 0 : buf.append( rtl::OStringToOUString( sql, pSettings->encoding ) );
362 : 0 : buf.appendAscii( "')" );
363 : 0 : OUString error = buf.makeStringAndClear();
364 : 0 : log( pSettings, LogLevel::ERROR, error );
365 : 0 : throw SQLException( error, owner, OUString(), 1, Any() );
366 : : }
367 : :
368 : :
369 : : // returns the elements of the primary key of the given table
370 : : // static Sequence< Reference< com::sun::star::beans::XPropertySet > > lookupKeys(
371 : 0 : static Sequence< ::rtl::OUString > lookupKeys(
372 : : const Reference< com::sun::star::container::XNameAccess > &tables,
373 : : const OUString & table,
374 : : OUString *pSchema,
375 : : OUString *pTable,
376 : : ConnectionSettings *pSettings)
377 : : {
378 : 0 : Sequence< ::rtl::OUString > ret;
379 : 0 : Reference< XKeysSupplier > keySupplier;
380 : 0 : Statics & st = getStatics();
381 : :
382 : 0 : if( tables->hasByName( table ) )
383 : 0 : tables->getByName( table ) >>= keySupplier;
384 : 0 : else if( -1 == table.indexOf( '.' ) )
385 : : {
386 : : // it wasn't a fully qualified name. Now need to skip through all tables.
387 : : Reference< XEnumerationAccess > enumerationAccess =
388 : 0 : Reference< XEnumerationAccess > ( tables, UNO_QUERY );
389 : :
390 : : Reference< com::sun::star::container::XEnumeration > enumeration =
391 : 0 : enumerationAccess->createEnumeration();
392 : 0 : while( enumeration->hasMoreElements() )
393 : : {
394 : 0 : Reference< XPropertySet > set;
395 : 0 : enumeration->nextElement() >>= set;
396 : 0 : OUString name;
397 : : // ::rtl::OUString schema;
398 : :
399 : 0 : if( set->getPropertyValue( st.NAME ) >>= name )
400 : : {
401 : : // printf( "searching %s %s\n",
402 : : // OUStringToOString( schema, RTL_TEXTENCODING_ASCII_US ).getStr(),
403 : : // OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ).getStr() );
404 : 0 : if( name == table )
405 : : {
406 : :
407 : 0 : if( keySupplier.is() )
408 : : {
409 : : // is ambigous, as I don't know postgresql searchpath,
410 : : // I can't continue here, as I may write to a different table
411 : 0 : keySupplier.clear();
412 : 0 : if( isLog( pSettings, LogLevel::INFO ) )
413 : : {
414 : 0 : rtl::OStringBuffer buf( 128 );
415 : 0 : buf.append( "Can't offer updateable result set because table " );
416 : 0 : buf.append( OUStringToOString(name, pSettings->encoding) );
417 : 0 : buf.append( " is duplicated, add schema to resolve ambiguity" );
418 : 0 : log( pSettings, LogLevel::INFO, buf.makeStringAndClear().getStr() );
419 : : }
420 : : break;
421 : : }
422 : 0 : keySupplier = Reference< XKeysSupplier > ( set, UNO_QUERY );
423 : : }
424 : : }
425 : 0 : }
426 : : }
427 : : else
428 : : {
429 : 0 : if( isLog( pSettings, LogLevel::INFO ) )
430 : : {
431 : 0 : rtl::OStringBuffer buf( 128 );
432 : 0 : buf.append( "Can't offer updateable result set ( table " );
433 : 0 : buf.append( OUStringToOString(table, pSettings->encoding) );
434 : 0 : buf.append( " is unknown)" );
435 : 0 : log( pSettings, LogLevel::INFO, buf.makeStringAndClear().getStr() );
436 : : }
437 : : }
438 : :
439 : 0 : if( keySupplier.is() )
440 : : {
441 : 0 : Reference< XPropertySet > set( keySupplier, UNO_QUERY );
442 : 0 : set->getPropertyValue( getStatics().NAME ) >>= (*pTable);
443 : 0 : set->getPropertyValue( getStatics().SCHEMA_NAME ) >>= (*pSchema );
444 : 0 : set.clear();
445 : :
446 : 0 : Reference< XEnumerationAccess > keys ( keySupplier->getKeys(), UNO_QUERY );
447 : 0 : Reference< XEnumeration > enumeration = keys->createEnumeration();
448 : 0 : while( enumeration->hasMoreElements() )
449 : : {
450 : 0 : enumeration->nextElement() >>= set;
451 : 0 : sal_Int32 keyType = 0;
452 : 0 : if( (set->getPropertyValue( st.TYPE ) >>= keyType ) &&
453 : : keyType == com::sun::star::sdbcx::KeyType::PRIMARY )
454 : : {
455 : 0 : Reference< XColumnsSupplier > columns( set, UNO_QUERY );
456 : : Reference< XIndexAccess > indexAccess =
457 : 0 : Reference< XIndexAccess > ( columns->getColumns(), UNO_QUERY );
458 : :
459 : 0 : int length = indexAccess->getCount();
460 : 0 : ret.realloc( length );
461 : : // printf( "primary key for Table %s is ",
462 : : // OUStringToOString( table, RTL_TEXTENCODING_ASCII_US ).getStr() );
463 : 0 : for( int i = 0 ; i < length ; i ++ )
464 : : {
465 : 0 : indexAccess->getByIndex( i ) >>= set;
466 : 0 : OUString name;
467 : 0 : set->getPropertyValue( st.NAME ) >>= name;
468 : 0 : ret[i] = name;
469 : : // printf( "%s," , OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ).getStr() );
470 : 0 : }
471 : : // printf( "\n" );
472 : : }
473 : : }
474 : 0 : if( ! ret.getLength() )
475 : : {
476 : 0 : if( isLog( pSettings, LogLevel::INFO ) )
477 : : {
478 : 0 : rtl::OStringBuffer buf( 128 );
479 : 0 : buf.append( "Can't offer updateable result set ( table " );
480 : 0 : buf.append( OUStringToOString(table, pSettings->encoding) );
481 : 0 : buf.append( " does not have a primary key)" );
482 : 0 : log( pSettings, LogLevel::INFO, buf.makeStringAndClear().getStr() );
483 : : }
484 : 0 : }
485 : : }
486 : 0 : return ret;
487 : : }
488 : :
489 : 0 : bool executePostgresCommand( const rtl::OString & cmd, struct CommandData *data )
490 : : {
491 : 0 : ConnectionSettings *pSettings = *(data->ppSettings);
492 : :
493 : 0 : sal_Int32 duration = osl_getGlobalTimer();
494 : 0 : PGresult *result = PQexec( pSettings->pConnection, cmd.getStr() );
495 : 0 : duration = osl_getGlobalTimer() - duration;
496 : 0 : if( ! result )
497 : : raiseSQLException(
498 : 0 : pSettings, data->owner, cmd, PQerrorMessage( pSettings->pConnection ) );
499 : :
500 : 0 : ExecStatusType state = PQresultStatus( result );
501 : 0 : *(data->pLastOidInserted) = 0;
502 : 0 : *(data->pLastTableInserted) = rtl::OUString();
503 : 0 : *(data->pLastQuery) = cmd;
504 : :
505 : 0 : sal_Bool ret = sal_False;
506 : 0 : switch( state )
507 : : {
508 : : case PGRES_COMMAND_OK:
509 : : {
510 : 0 : *(data->pMultipleResultUpdateCount) = atoi( PQcmdTuples( result ) );
511 : 0 : *(data->pMultipleResultAvailable) = sal_False;
512 : :
513 : : // in case an oid value is available, we retrieve it
514 : 0 : *(data->pLastOidInserted) = PQoidValue( result );
515 : :
516 : : // in case it was a single insert, extract the name of the table,
517 : : // otherwise the table name is empty
518 : : *(data->pLastTableInserted) =
519 : 0 : extractTableFromInsert( OStringToOUString( cmd, pSettings->encoding ) );
520 : 0 : if( isLog( pSettings, LogLevel::SQL ) )
521 : : {
522 : 0 : rtl::OStringBuffer buf( 128 );
523 : 0 : buf.append( "executed command '" );
524 : 0 : buf.append( cmd.getStr() );
525 : 0 : buf.append( "' sucessfully (" );
526 : 0 : buf.append( *( data->pMultipleResultUpdateCount ) );
527 : 0 : buf.append( ")" );
528 : 0 : buf.append( ", duration=" );
529 : 0 : buf.append( duration );
530 : 0 : buf.append( "ms" );
531 : 0 : if( *(data->pLastOidInserted) )
532 : : {
533 : 0 : buf.append( ", usedOid=" );
534 : 0 : buf.append( *(data->pLastOidInserted) , 10 );
535 : 0 : buf.append( ", diagnosedTable=" );
536 : : buf.append(
537 : 0 : OUStringToOString( *data->pLastTableInserted, pSettings->encoding ) );
538 : : }
539 : 0 : log( pSettings, LogLevel::SQL, buf.makeStringAndClear().getStr() );
540 : : }
541 : 0 : PQclear( result );
542 : 0 : break;
543 : : }
544 : : case PGRES_TUPLES_OK: // success
545 : : {
546 : : // In case it is a single table, it has a primary key and all columns
547 : : // belonging to the primary key are in the result set, allow updateable result sets
548 : : // otherwise, don't
549 : 0 : rtl::OUString table, schema;
550 : 0 : Sequence< OUString > sourceTableKeys;
551 : 0 : OStringVector vec;
552 : 0 : tokenizeSQL( cmd, vec );
553 : : OUString sourceTable =
554 : : OStringToOUString(
555 : 0 : extractSingleTableFromSelect( vec ), pSettings->encoding );
556 : :
557 : 0 : if( data->concurrency ==
558 : : com::sun::star::sdbc::ResultSetConcurrency::UPDATABLE )
559 : : {
560 : 0 : OString aReason;
561 : 0 : if( sourceTable.getLength() )
562 : : {
563 : : sourceTableKeys = lookupKeys(
564 : 0 : pSettings->tables.is() ?
565 : 0 : pSettings->tables : data->tableSupplier->getTables() ,
566 : : sourceTable,
567 : : &schema,
568 : : &table,
569 : 0 : pSettings);
570 : :
571 : : // check, whether the columns are in the result set (required !)
572 : : int i;
573 : 0 : for( i = 0 ; i < sourceTableKeys.getLength() ; i ++ )
574 : : {
575 : 0 : if( -1 == PQfnumber(
576 : : result,
577 : 0 : OUStringToOString( sourceTableKeys[i] ,
578 : 0 : pSettings->encoding ).getStr()) )
579 : : {
580 : 0 : break;
581 : : }
582 : : }
583 : :
584 : 0 : if( sourceTableKeys.getLength() && i == sourceTableKeys.getLength() )
585 : : {
586 : : *(data->pLastResultset) =
587 : : UpdateableResultSet::createFromPGResultSet(
588 : : data->refMutex, data->owner, data->ppSettings, result,
589 : 0 : schema, table,sourceTableKeys );
590 : : }
591 : 0 : else if( ! table.getLength() )
592 : : {
593 : 0 : rtl::OStringBuffer buf( 128 );
594 : : buf.append(
595 : : RTL_CONSTASCII_STRINGPARAM(
596 : : "can't support updateable resultset, because a single table in the "
597 : 0 : "WHERE part of the statement could not be identified (" ) );
598 : 0 : buf.append( cmd );
599 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( "." ) );
600 : 0 : aReason = buf.makeStringAndClear();
601 : : }
602 : 0 : else if( sourceTableKeys.getLength() )
603 : : {
604 : 0 : ::rtl::OStringBuffer buf( 128 );
605 : : buf.append(
606 : : RTL_CONSTASCII_STRINGPARAM(
607 : 0 : "can't support updateable resultset for table " ) );
608 : 0 : buf.append( rtl::OUStringToOString( schema, pSettings->encoding ) );
609 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( "." ) );
610 : 0 : buf.append( rtl::OUStringToOString( table, pSettings->encoding ) );
611 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( ", because resultset does not contain a part of the primary key ( column " ) );
612 : 0 : buf.append( rtl::OUStringToOString( sourceTableKeys[i], pSettings->encoding ) );
613 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( " is missing )") );
614 : 0 : aReason = buf.makeStringAndClear();
615 : : }
616 : : else
617 : : {
618 : :
619 : 0 : ::rtl::OStringBuffer buf( 128 );
620 : : buf.append(
621 : : RTL_CONSTASCII_STRINGPARAM(
622 : 0 : "can't support updateable resultset for table " ) );
623 : 0 : buf.append( rtl::OUStringToOString( schema, pSettings->encoding ) );
624 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( "." ) );
625 : 0 : buf.append( rtl::OUStringToOString( table, pSettings->encoding ) );
626 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( ", because resultset table does not have a primary key " ) );
627 : 0 : aReason = buf.makeStringAndClear();
628 : : }
629 : : }
630 : : else
631 : : {
632 : 0 : ::rtl::OStringBuffer buf( 128 );
633 : : buf.append(
634 : : RTL_CONSTASCII_STRINGPARAM(
635 : 0 : "can't support updateable result for selects with multiple tables (" ) );
636 : 0 : buf.append( cmd );
637 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM( ")" ) );
638 : 0 : log( pSettings, LogLevel::SQL, buf.makeStringAndClear().getStr() );
639 : : }
640 : 0 : if( ! (*(data->pLastResultset)).is() )
641 : : {
642 : 0 : if( isLog( pSettings, LogLevel::ERROR ) )
643 : : {
644 : 0 : log( pSettings, LogLevel::ERROR, aReason.getStr());
645 : : }
646 : :
647 : : // TODO: How to react here correctly ?
648 : : // remove this piece of code
649 : : *(data->pLastResultset) =
650 : : new FakedUpdateableResultSet(
651 : : data->refMutex, data->owner,
652 : : data->ppSettings,result, schema, table,
653 : 0 : OStringToOUString( aReason, pSettings->encoding) );
654 : 0 : }
655 : :
656 : : }
657 : 0 : else if( sourceTable.getLength() && -1 != sourceTable.indexOf( '.' ) )
658 : : {
659 : 0 : splitConcatenatedIdentifier( sourceTable, &schema, &table );
660 : : }
661 : :
662 : 0 : sal_Int32 returnedRows = PQntuples( result );
663 : 0 : if( ! data->pLastResultset->is() )
664 : : *(data->pLastResultset) =
665 : : Reference< XCloseable > (
666 : : new ResultSet(
667 : : data->refMutex, data->owner,
668 : 0 : data->ppSettings,result, schema, table ) );
669 : 0 : *(data->pMultipleResultAvailable) = sal_True;
670 : 0 : ret = sal_True;
671 : 0 : if( isLog( pSettings, LogLevel::SQL ) )
672 : : {
673 : 0 : rtl::OStringBuffer buf( 128 );
674 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM("executed query '") );
675 : 0 : buf.append( cmd );
676 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM("' sucessfully") );
677 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM(", duration=") );
678 : 0 : buf.append( duration );
679 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM("ms, returnedRows=") );
680 : 0 : buf.append( returnedRows );
681 : 0 : buf.append( RTL_CONSTASCII_STRINGPARAM("." ) );
682 : 0 : log( pSettings, LogLevel::SQL, buf.makeStringAndClear().getStr() );
683 : : }
684 : 0 : break;
685 : : }
686 : : case PGRES_EMPTY_QUERY:
687 : : case PGRES_COPY_OUT:
688 : : case PGRES_COPY_IN:
689 : : case PGRES_BAD_RESPONSE:
690 : : case PGRES_NONFATAL_ERROR:
691 : : case PGRES_FATAL_ERROR:
692 : : default:
693 : : raiseSQLException(
694 : 0 : pSettings, data->owner, cmd, PQresultErrorMessage( result ) , PQresStatus( state ) );
695 : : }
696 : 0 : return ret;
697 : :
698 : : }
699 : :
700 : 0 : static Sequence< OUString > getPrimaryKeyColumnNames(
701 : : const Reference< XConnection > & connection, const OUString &schemaName, const OUString &tableName )
702 : : {
703 : 0 : Sequence< OUString > ret;
704 : :
705 : 0 : Int2StringMap mapIndex2Name;
706 : 0 : fillAttnum2attnameMap( mapIndex2Name, connection, schemaName, tableName );
707 : :
708 : : // retrieve the primary key ...
709 : 0 : Reference< XPreparedStatement > stmt = connection->prepareStatement(
710 : : ASCII_STR(
711 : : "SELECT conkey " // 7
712 : : "FROM pg_constraint INNER JOIN pg_class ON conrelid = pg_class.oid "
713 : : "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
714 : : "LEFT JOIN pg_class AS class2 ON confrelid = class2.oid "
715 : : "LEFT JOIN pg_namespace AS nmsp2 ON class2.relnamespace=nmsp2.oid "
716 : 0 : "WHERE pg_class.relname = ? AND pg_namespace.nspname = ? AND pg_constraint.contype='p'" ) );
717 : 0 : DisposeGuard guard( stmt );
718 : 0 : Reference< XParameters > paras( stmt, UNO_QUERY );
719 : 0 : paras->setString( 1 , tableName );
720 : 0 : paras->setString( 2 , schemaName );
721 : 0 : Reference< XResultSet > rs = stmt->executeQuery();
722 : 0 : Reference< XRow > xRow( rs , UNO_QUERY );
723 : :
724 : 0 : if( rs->next() )
725 : : {
726 : 0 : ret = convertMappedIntArray2StringArray( mapIndex2Name, string2intarray(xRow->getString( 1 ) ) );
727 : : }
728 : 0 : return ret;
729 : : }
730 : :
731 : 0 : static void getAutoValues(
732 : : String2StringMap & result,
733 : : const Reference< XConnection > & connection,
734 : : const OUString &schemaName,
735 : : const OUString & tableName )
736 : : {
737 : 0 : Reference< XPreparedStatement > stmt = connection->prepareStatement(
738 : : ASCII_STR("SELECT pg_attribute.attname, pg_attrdef.adsrc "
739 : : "FROM pg_class, pg_namespace, pg_attribute "
740 : : "LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND "
741 : : "pg_attribute.attnum = pg_attrdef.adnum "
742 : : "WHERE pg_attribute.attrelid = pg_class.oid AND "
743 : : "pg_class.relnamespace = pg_namespace.oid AND "
744 : : "pg_namespace.nspname = ? AND "
745 : : // LEM TODO: this is weird; why "LIKE" and not "="?
746 : : // Most probably gives problems if tableName contains '%'
747 : : "pg_class.relname LIKE ? AND "
748 : : "pg_attrdef.adsrc != ''"
749 : 0 : ) );
750 : 0 : DisposeGuard guard( stmt );
751 : 0 : Reference< XParameters > paras( stmt, UNO_QUERY );
752 : 0 : paras->setString( 1 , schemaName );
753 : 0 : paras->setString( 2 , tableName );
754 : 0 : Reference< XResultSet > rs = stmt->executeQuery();
755 : 0 : Reference< XRow > xRow( rs , UNO_QUERY );
756 : :
757 : 0 : while( rs->next() )
758 : : {
759 : 0 : result[ OUStringToOString( xRow->getString( 1 ), RTL_TEXTENCODING_ASCII_US) ] =
760 : 0 : OUStringToOString( xRow->getString(2), RTL_TEXTENCODING_ASCII_US );
761 : 0 : }
762 : 0 : }
763 : :
764 : 0 : Reference< XResultSet > getGeneratedValuesFromLastInsert(
765 : : ConnectionSettings *pConnectionSettings,
766 : : const Reference< XConnection > &connection,
767 : : sal_Int32 nLastOid,
768 : : const rtl::OUString & lastTableInserted,
769 : : const rtl::OString & lastQuery )
770 : : {
771 : 0 : Reference< XResultSet > ret;
772 : 0 : OUString query;
773 : 0 : OUString schemaName, tableName;
774 : : splitConcatenatedIdentifier(
775 : 0 : lastTableInserted, &schemaName, &tableName );
776 : :
777 : 0 : if( nLastOid && lastTableInserted.getLength() )
778 : : {
779 : 0 : OUStringBuffer buf( 128 );
780 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SELECT * FROM " ) );
781 : 0 : if( schemaName.getLength() )
782 : 0 : bufferQuoteQualifiedIdentifier(buf, schemaName, tableName, pConnectionSettings );
783 : : else
784 : 0 : bufferQuoteIdentifier( buf, lastTableInserted, pConnectionSettings );
785 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " WHERE oid = " ) );
786 : 0 : buf.append( nLastOid , 10 );
787 : 0 : query = buf.makeStringAndClear();
788 : : }
789 : 0 : else if ( lastTableInserted.getLength() && lastQuery.getLength() )
790 : : {
791 : : // extract nameValue Pairs
792 : 0 : String2StringMap namedValues;
793 : 0 : extractNameValuePairsFromInsert( namedValues, lastQuery );
794 : :
795 : : // debug ...
796 : : // rtl::OStringBuffer buf( 128);
797 : : // buf.append( "extracting name/value from '" );
798 : : // buf.append( lastQuery.getStr() );
799 : : // buf.append( "' to [" );
800 : : // for( String2StringMap::iterator ii = namedValues.begin() ; ii != namedValues.end() ; ++ii )
801 : : // {
802 : : // buf.append( ii->first.getStr() );
803 : : // buf.append( "=" );
804 : : // buf.append( ii->second.getStr() );
805 : : // buf.append( "," );
806 : : // }
807 : : // buf.append( "]\n" );
808 : : // printf( "%s", buf.makeStringAndClear() );
809 : :
810 : : // TODO: make also unqualified tables names work here. Have a look at 2.8.3. The Schema Search Path
811 : : // in postgresql doc
812 : :
813 : 0 : Sequence< OUString > keyColumnNames = getPrimaryKeyColumnNames( connection, schemaName, tableName );
814 : 0 : if( keyColumnNames.getLength() )
815 : : {
816 : 0 : OUStringBuffer buf( 128 );
817 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SELECT * FROM " ) );
818 : 0 : bufferQuoteQualifiedIdentifier(buf, schemaName, tableName, pConnectionSettings );
819 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " WHERE " ) );
820 : 0 : bool additionalCondition = false;
821 : 0 : String2StringMap autoValues;
822 : 0 : for( int i = 0 ; i < keyColumnNames.getLength() ; i ++ )
823 : : {
824 : 0 : OUString value;
825 : 0 : OString columnName = OUStringToOString( keyColumnNames[i], pConnectionSettings->encoding );
826 : 0 : String2StringMap::iterator ii = namedValues.begin();
827 : 0 : for( ; ii != namedValues.end() ; ++ii )
828 : : {
829 : 0 : if( columnName.equalsIgnoreAsciiCase( ii->first ) )
830 : : {
831 : 0 : value = OStringToOUString( ii->second , pConnectionSettings->encoding );
832 : 0 : break;
833 : : }
834 : : }
835 : :
836 : : // check, if a column of the primary key was not inserted explicitly,
837 : 0 : if( ii == namedValues.end() )
838 : : {
839 : :
840 : 0 : if( autoValues.begin() == autoValues.end() )
841 : : {
842 : 0 : getAutoValues( autoValues, connection, schemaName, tableName );
843 : : }
844 : : // this could mean, that the column is a default or auto value, check this ...
845 : 0 : String2StringMap::iterator j = autoValues.begin();
846 : 0 : for( ; j != autoValues.end() ; ++j )
847 : : {
848 : 0 : if( columnName.equalsIgnoreAsciiCase( j->first ) )
849 : : {
850 : : // it is indeed an auto value.
851 : 0 : value = OStringToOUString(j->second, RTL_TEXTENCODING_ASCII_US );
852 : : // check, whether it is a sequence
853 : :
854 : 0 : if( rtl_str_shortenedCompare_WithLength(
855 : 0 : j->second.getStr(), j->second.getLength(),
856 : 0 : RTL_CONSTASCII_STRINGPARAM( "nextval(" ), 8 ) == 0 )
857 : : {
858 : : // retrieve current sequence value:
859 : 0 : OUStringBuffer myBuf(128 );
860 : 0 : myBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "SELECT currval(" ) );
861 : 0 : myBuf.appendAscii( &(j->second.getStr()[8]));
862 : 0 : value = querySingleValue( connection, myBuf.makeStringAndClear() );
863 : : }
864 : 0 : break;
865 : : }
866 : : }
867 : 0 : if( j == autoValues.end() )
868 : : {
869 : : // it even was no autovalue, no sense to continue as we can't query the
870 : : // inserted row
871 : 0 : buf = OUStringBuffer();
872 : : break;
873 : : }
874 : : }
875 : :
876 : 0 : if( additionalCondition )
877 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " AND " ) );
878 : 0 : bufferQuoteIdentifier( buf, keyColumnNames[i], pConnectionSettings );
879 : 0 : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ) );
880 : 0 : buf.append( value );
881 : 0 : additionalCondition = true;
882 : 0 : }
883 : 0 : query = buf.makeStringAndClear();
884 : 0 : }
885 : : }
886 : :
887 : 0 : if( query.getLength() )
888 : : {
889 : 0 : Reference< com::sun::star::sdbc::XStatement > stmt = connection->createStatement();
890 : 0 : ret = stmt->executeQuery( query );
891 : : }
892 : :
893 : 0 : return ret;
894 : :
895 : : }
896 : :
897 : 0 : sal_Bool Statement::execute( const OUString& sql )
898 : : throw (SQLException, RuntimeException)
899 : : {
900 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
901 : 0 : checkClosed();
902 : 0 : OString cmd = OUStringToOString( sql, m_pSettings );
903 : :
904 : 0 : m_lastResultset.clear();
905 : 0 : m_lastTableInserted = rtl::OUString();
906 : :
907 : 0 : struct CommandData data;
908 : 0 : data.refMutex = m_refMutex;
909 : 0 : data.ppSettings = &m_pSettings;
910 : 0 : data.pLastOidInserted = &m_lastOidInserted;
911 : 0 : data.pLastQuery = &m_lastQuery;
912 : 0 : data.pMultipleResultUpdateCount = &m_multipleResultUpdateCount;
913 : 0 : data.pMultipleResultAvailable = &m_multipleResultAvailable;
914 : 0 : data.pLastTableInserted = &m_lastTableInserted;
915 : 0 : data.pLastResultset = &m_lastResultset;
916 : 0 : data.owner = *this;
917 : 0 : data.tableSupplier = Reference< com::sun::star::sdbcx::XTablesSupplier >( m_connection, UNO_QUERY );
918 : : data.concurrency =
919 : 0 : extractIntProperty( this, getStatics().RESULT_SET_CONCURRENCY );
920 : 0 : return executePostgresCommand( cmd , &data );
921 : : }
922 : :
923 : 0 : Reference< XConnection > Statement::getConnection( )
924 : : throw (SQLException, RuntimeException)
925 : : {
926 : 0 : Reference< XConnection > ret;
927 : : {
928 : 0 : MutexGuard guard( m_refMutex->mutex );
929 : 0 : checkClosed();
930 : 0 : ret = m_connection;
931 : : }
932 : 0 : return ret;
933 : : }
934 : :
935 : :
936 : 0 : Any Statement::getWarnings( )
937 : : throw (SQLException,RuntimeException)
938 : : {
939 : 0 : return Any();
940 : : }
941 : :
942 : 0 : void Statement::clearWarnings( )
943 : : throw (SQLException, RuntimeException)
944 : : {
945 : 0 : }
946 : :
947 : 0 : Reference< ::com::sun::star::sdbc::XResultSetMetaData > Statement::getMetaData()
948 : : throw (SQLException,RuntimeException)
949 : : {
950 : 0 : Reference< com::sun::star::sdbc::XResultSetMetaData > ret;
951 : 0 : Reference< com::sun::star::sdbc::XResultSetMetaDataSupplier > supplier( m_lastResultset, UNO_QUERY );
952 : 0 : if( supplier.is() )
953 : 0 : ret = supplier->getMetaData();
954 : 0 : return ret;
955 : : }
956 : :
957 : :
958 : 0 : ::cppu::IPropertyArrayHelper & Statement::getInfoHelper()
959 : : {
960 : 0 : return getStatementPropertyArrayHelper();
961 : : }
962 : :
963 : :
964 : 0 : sal_Bool Statement::convertFastPropertyValue(
965 : : Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
966 : : throw (IllegalArgumentException)
967 : : {
968 : 0 : rOldValue = m_props[nHandle];
969 : : sal_Bool bRet;
970 : 0 : switch( nHandle )
971 : : {
972 : : case STATEMENT_CURSOR_NAME:
973 : : {
974 : 0 : OUString val;
975 : 0 : bRet = ( rValue >>= val );
976 : 0 : rConvertedValue = makeAny( val );
977 : 0 : break;
978 : : }
979 : : case STATEMENT_ESCAPE_PROCESSING:
980 : : {
981 : : sal_Bool val;
982 : 0 : bRet = ( rValue >>= val );
983 : 0 : rConvertedValue = makeAny( val );
984 : : break;
985 : : }
986 : : case STATEMENT_FETCH_DIRECTION:
987 : : case STATEMENT_FETCH_SIZE:
988 : : case STATEMENT_MAX_FIELD_SIZE:
989 : : case STATEMENT_MAX_ROWS:
990 : : case STATEMENT_QUERY_TIME_OUT:
991 : : case STATEMENT_RESULT_SET_CONCURRENCY:
992 : : case STATEMENT_RESULT_SET_TYPE:
993 : : {
994 : : sal_Int32 val;
995 : 0 : bRet = ( rValue >>= val );
996 : 0 : rConvertedValue = makeAny( val );
997 : : break;
998 : : }
999 : : default:
1000 : : {
1001 : 0 : OUStringBuffer buf(128);
1002 : 0 : buf.appendAscii( "pq_statement: Invalid property handle (" );
1003 : 0 : buf.append( nHandle );
1004 : 0 : buf.appendAscii( ")" );
1005 : 0 : throw IllegalArgumentException( buf.makeStringAndClear(), *this, 2 );
1006 : : }
1007 : : }
1008 : 0 : return bRet;
1009 : : }
1010 : :
1011 : :
1012 : 0 : void Statement::setFastPropertyValue_NoBroadcast(
1013 : : sal_Int32 nHandle,const Any& rValue ) throw (Exception)
1014 : : {
1015 : 0 : m_props[nHandle] = rValue;
1016 : 0 : }
1017 : :
1018 : 0 : void Statement::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1019 : : {
1020 : 0 : rValue = m_props[nHandle];
1021 : 0 : }
1022 : :
1023 : 0 : Reference < XPropertySetInfo > Statement::getPropertySetInfo()
1024 : : throw(RuntimeException)
1025 : : {
1026 : 0 : return OPropertySetHelper::createPropertySetInfo( getStatementPropertyArrayHelper() );
1027 : : }
1028 : :
1029 : :
1030 : 0 : Reference< XResultSet > Statement::getResultSet( )
1031 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
1032 : : {
1033 : 0 : return Reference< XResultSet > ( m_lastResultset, com::sun::star::uno::UNO_QUERY );
1034 : : }
1035 : :
1036 : 0 : sal_Int32 Statement::getUpdateCount( )
1037 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
1038 : : {
1039 : 0 : return m_multipleResultUpdateCount;
1040 : : }
1041 : :
1042 : 0 : sal_Bool Statement::getMoreResults( )
1043 : : throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
1044 : : {
1045 : 0 : return sal_False;
1046 : : }
1047 : :
1048 : :
1049 : :
1050 : 0 : void Statement::disposing()
1051 : : {
1052 : 0 : close();
1053 : 0 : }
1054 : :
1055 : 0 : Reference< XResultSet > Statement::getGeneratedValues( )
1056 : : throw (SQLException, RuntimeException)
1057 : : {
1058 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
1059 : : return getGeneratedValuesFromLastInsert(
1060 : 0 : m_pSettings, m_connection, m_lastOidInserted, m_lastTableInserted, m_lastQuery );
1061 : : }
1062 : :
1063 : : }
|