LCOV - code coverage report
Current view: top level - connectivity/source/drivers/postgresql - pq_connection.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 323 0.0 %
Date: 2014-11-03 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

          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 <list>
      38             : #include <stdio.h>
      39             : #include <time.h>
      40             : #include <string.h>
      41             : 
      42             : #include <boost/shared_ptr.hpp>
      43             : 
      44             : #include "pq_connection.hxx"
      45             : #include "pq_statement.hxx"
      46             : #include "pq_preparedstatement.hxx"
      47             : #include "pq_databasemetadata.hxx"
      48             : #include "pq_xcontainer.hxx"
      49             : #include "pq_statics.hxx"
      50             : #include "pq_xtables.hxx"
      51             : #include "pq_xviews.hxx"
      52             : #include "pq_xusers.hxx"
      53             : 
      54             : #include <rtl/ustrbuf.hxx>
      55             : #include <rtl/strbuf.hxx>
      56             : #include <rtl/uuid.h>
      57             : #include <rtl/bootstrap.hxx>
      58             : #include <osl/module.h>
      59             : 
      60             : #include <cppuhelper/implementationentry.hxx>
      61             : #include <cppuhelper/implbase1.hxx>
      62             : 
      63             : #include <com/sun/star/beans/PropertyValue.hpp>
      64             : #include <com/sun/star/script/Converter.hpp>
      65             : #include <com/sun/star/sdbc/XRow.hpp>
      66             : 
      67             : using osl::MutexGuard;
      68             : 
      69             : using com::sun::star::container::XNameAccess;
      70             : 
      71             : using com::sun::star::lang::XComponent;
      72             : using com::sun::star::lang::XInitialization;
      73             : using com::sun::star::lang::IllegalArgumentException;
      74             : 
      75             : using com::sun::star::script::Converter;
      76             : using com::sun::star::script::XTypeConverter;
      77             : 
      78             : using com::sun::star::uno::RuntimeException;
      79             : using com::sun::star::uno::Exception;
      80             : using com::sun::star::uno::Sequence;
      81             : using com::sun::star::uno::Reference;
      82             : using com::sun::star::uno::XInterface;
      83             : using com::sun::star::uno::UNO_QUERY;
      84             : using com::sun::star::uno::XComponentContext;
      85             : using com::sun::star::uno::Any;
      86             : using com::sun::star::uno::makeAny;
      87             : 
      88             : using com::sun::star::beans::PropertyValue;
      89             : using com::sun::star::beans::XPropertySet;
      90             : 
      91             : using com::sun::star::sdbc::XConnection;
      92             : using com::sun::star::sdbc::XResultSet;
      93             : using com::sun::star::sdbc::XRow;
      94             : using com::sun::star::sdbc::XCloseable;
      95             : using com::sun::star::sdbc::SQLException;
      96             : using com::sun::star::sdbc::XWarningsSupplier;
      97             : using com::sun::star::sdbc::XPreparedStatement;
      98             : using com::sun::star::sdbc::XStatement;
      99             : using com::sun::star::sdbc::XDatabaseMetaData;
     100             : 
     101             : namespace pq_sdbc_driver
     102             : {
     103             : 
     104             : 
     105             : 
     106             : // Helper class for statement lifetime management
     107             : class ClosableReference : public cppu::WeakImplHelper1< com::sun::star::uno::XReference >
     108             : {
     109             :     Connection *m_conn;
     110             :     ::rtl::ByteSequence m_id;
     111             : public:
     112           0 :     ClosableReference( const ::rtl::ByteSequence & id , Connection *that )
     113           0 :       :  m_conn( that ), m_id( id )
     114             :     {
     115           0 :         that->acquire();
     116           0 :     }
     117             : 
     118           0 :     virtual ~ClosableReference()
     119           0 :     {
     120           0 :         if( m_conn )
     121           0 :             m_conn->release();
     122           0 :     }
     123             : 
     124           0 :     virtual void SAL_CALL dispose() throw (std::exception) SAL_OVERRIDE
     125             :     {
     126           0 :         if( m_conn )
     127             :         {
     128           0 :             m_conn->removeFromWeakMap(m_id);
     129           0 :             m_conn->release();
     130           0 :             m_conn = 0;
     131             :         }
     132           0 :     }
     133             : };
     134             : 
     135           0 : OUString    ConnectionGetImplementationName()
     136             : {
     137           0 :     return OUString( "org.openoffice.comp.connectivity.pq.Connection.noext" );
     138             : }
     139           0 : com::sun::star::uno::Sequence<OUString> ConnectionGetSupportedServiceNames(void)
     140             : {
     141           0 :     OUString serv( "com.sun.star.sdbc.Connection" );
     142           0 :     return Sequence< OUString> (&serv,1);
     143             : }
     144             : 
     145           0 : static sal_Int32 readLogLevelFromConfiguration()
     146             : {
     147           0 :     sal_Int32 loglevel = LogLevel::NONE;
     148           0 :     OUString fileName;
     149             :     osl_getModuleURLFromAddress(
     150           0 :         (void*) readLogLevelFromConfiguration, (rtl_uString **) &fileName );
     151           0 :     fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
     152             : #ifdef MACOSX
     153             :     fileName += "../Resources/";
     154             : #endif
     155           0 :     fileName += "postgresql-sdbc.ini";
     156           0 :     rtl::Bootstrap bootstrapHandle( fileName );
     157             : 
     158           0 :     OUString str;
     159           0 :     if( bootstrapHandle.getFrom( "PQ_LOGLEVEL", str ) )
     160             :     {
     161           0 :         if ( str == "NONE" )
     162           0 :             loglevel = LogLevel::NONE;
     163           0 :         else if ( str == "ERROR" )
     164           0 :             loglevel = LogLevel::ERROR;
     165           0 :         else if ( str == "SQL" )
     166           0 :             loglevel = LogLevel::SQL;
     167           0 :         else if ( str == "INFO" )
     168           0 :             loglevel = LogLevel::INFO;
     169             :         else
     170             :         {
     171             :             fprintf( stderr, "unknown loglevel %s\n",
     172           0 :                      OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
     173             :         }
     174             :     }
     175           0 :     return loglevel;
     176             : }
     177             : 
     178           0 : Connection::Connection(
     179             :     const rtl::Reference< RefCountedMutex > &refMutex,
     180             :     const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & ctx )
     181           0 :     : ConnectionBase( refMutex->mutex ),
     182             :       m_ctx( ctx ) ,
     183           0 :       m_refMutex( refMutex )
     184             : {
     185           0 :     m_settings.loglevel = readLogLevelFromConfiguration();
     186             : 
     187           0 :     if( m_settings.loglevel > LogLevel::NONE )
     188             :     {
     189           0 :         m_settings.logFile = fopen( "sdbc-pqsql.log", "a" );
     190           0 :         if( m_settings.logFile )
     191             :         {
     192           0 :             setvbuf( m_settings.logFile, 0, _IONBF, 0 );
     193           0 :             log( &m_settings, m_settings.loglevel , "set this loglevel" );
     194             :         }
     195             :         else
     196             :         {
     197           0 :             fprintf( stderr, "Couldn't open sdbc-pqsql.log file\n" );
     198             :         }
     199             :     }
     200           0 : }
     201             : 
     202           0 : Connection::~Connection()
     203             : {
     204             :     POSTGRE_TRACE( "dtor connection" );
     205           0 :     if( m_settings.pConnection )
     206             :     {
     207           0 :         PQfinish( m_settings.pConnection );
     208           0 :         m_settings.pConnection = 0;
     209             :     }
     210           0 :     if( m_settings.logFile )
     211             :     {
     212           0 :         fclose( m_settings.logFile );
     213           0 :         m_settings.logFile = 0;
     214             :     }
     215           0 : }
     216             : typedef ::std::list< ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XCloseable > > CloseableList;
     217             : 
     218             : typedef ::std::list< ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > > DisposeableList;
     219             : 
     220           0 : void Connection::close() throw ( SQLException, RuntimeException, std::exception )
     221             : {
     222           0 :     CloseableList lst;
     223           0 :     DisposeableList lstDispose;
     224             :     {
     225           0 :         MutexGuard guard( m_refMutex->mutex );
     226             :         // silently ignore, if the connection has been closed already
     227           0 :         if( m_settings.pConnection )
     228             :         {
     229           0 :             log( &m_settings, LogLevel::INFO, "closing connection" );
     230           0 :             PQfinish( m_settings.pConnection );
     231           0 :             m_settings.pConnection = 0;
     232             :         }
     233             : 
     234           0 :         lstDispose.push_back( Reference< XComponent > ( m_settings.users, UNO_QUERY ) );
     235           0 :         lstDispose.push_back( Reference< XComponent > ( m_settings.tables , UNO_QUERY ) );
     236           0 :         lstDispose.push_back( Reference< XComponent > ( m_meta, UNO_QUERY ) );
     237           0 :         m_meta.clear();
     238           0 :         m_settings.tables.clear();
     239           0 :         m_settings.users.clear();
     240             : 
     241           0 :         for( WeakHashMap::iterator ii = m_myStatements.begin() ;
     242           0 :              ii != m_myStatements.end() ;
     243             :              ++ii )
     244             :         {
     245           0 :             Reference< XCloseable > r = ii->second;
     246           0 :             if( r.is() )
     247           0 :                 lst.push_back( r );
     248           0 :         }
     249             :     }
     250             : 
     251             :     // close all created statements
     252           0 :     for( CloseableList::iterator ii = lst.begin(); ii != lst.end() ; ++ii )
     253           0 :         ii->get()->close();
     254             : 
     255             :     // close all created statements
     256           0 :     for( DisposeableList::iterator iiDispose = lstDispose.begin();
     257           0 :          iiDispose != lstDispose.end() ; ++iiDispose )
     258             :     {
     259           0 :         if( iiDispose->is() )
     260           0 :             iiDispose->get()->dispose();
     261           0 :     }
     262           0 : }
     263             : 
     264             : 
     265           0 : void Connection::removeFromWeakMap( const ::rtl::ByteSequence & id )
     266             : {
     267             :     // shrink the list !
     268           0 :     MutexGuard guard( m_refMutex->mutex );
     269           0 :     WeakHashMap::iterator ii = m_myStatements.find( id );
     270           0 :     if( ii != m_myStatements.end() )
     271           0 :         m_myStatements.erase( ii );
     272           0 : }
     273             : 
     274           0 : Reference< XStatement > Connection::createStatement() throw (SQLException, RuntimeException, std::exception)
     275             : {
     276           0 :     MutexGuard guard( m_refMutex->mutex );
     277           0 :     checkClosed();
     278             : 
     279           0 :     Statement *stmt = new Statement( m_refMutex, this , &m_settings );
     280           0 :     Reference< XStatement > ret( stmt );
     281           0 :     ::rtl::ByteSequence id( 16 );
     282           0 :     rtl_createUuid( (sal_uInt8*) id.getConstArray(), 0 , sal_False );
     283           0 :     m_myStatements[ id ] = Reference< XCloseable > ( stmt );
     284           0 :     stmt->queryAdapter()->addReference( new ClosableReference( id, this ) );
     285           0 :     return ret;
     286             : }
     287             : 
     288           0 : Reference< XPreparedStatement > Connection::prepareStatement( const OUString& sql )
     289             :         throw (SQLException, RuntimeException, std::exception)
     290             : {
     291           0 :     MutexGuard guard( m_refMutex->mutex );
     292           0 :     checkClosed();
     293             : 
     294           0 :     OString byteSql = OUStringToOString( sql, m_settings.encoding );
     295           0 :     PreparedStatement *stmt = new PreparedStatement( m_refMutex, this, &m_settings, byteSql );
     296           0 :     Reference< XPreparedStatement > ret = stmt;
     297             : 
     298           0 :     ::rtl::ByteSequence id( 16 );
     299           0 :     rtl_createUuid( (sal_uInt8*) id.getConstArray(), 0 , sal_False );
     300           0 :     m_myStatements[ id ] = Reference< XCloseable > ( stmt );
     301           0 :     stmt->queryAdapter()->addReference( new ClosableReference( id, this ) );
     302           0 :     return ret;
     303             : }
     304             : 
     305           0 : Reference< XPreparedStatement > Connection::prepareCall( const OUString& )
     306             :         throw (SQLException, RuntimeException, std::exception)
     307             : {
     308             :     throw SQLException(
     309             :         "pq_driver: Callable statements not supported",
     310           0 :         Reference< XInterface > (), OUString() , 1, Any() );
     311             : }
     312             : 
     313             : 
     314           0 : OUString Connection::nativeSQL( const OUString& sql )
     315             :         throw (SQLException, RuntimeException, std::exception)
     316             : {
     317           0 :     return sql;
     318             : }
     319             : 
     320           0 : void Connection::setAutoCommit( sal_Bool ) throw (SQLException, RuntimeException, std::exception)
     321             : {
     322             :     // UNSUPPORTED
     323           0 : }
     324             : 
     325           0 : sal_Bool Connection::getAutoCommit() throw (SQLException, RuntimeException, std::exception)
     326             : {
     327             :     // UNSUPPORTED
     328           0 :     return sal_True;
     329             : }
     330             : 
     331           0 : void Connection::commit() throw (SQLException, RuntimeException, std::exception)
     332             : {
     333             :     // UNSUPPORTED
     334           0 : }
     335             : 
     336           0 : void Connection::rollback() throw (SQLException, RuntimeException, std::exception)
     337             : {
     338             :     // UNSUPPORTED
     339           0 : }
     340             : 
     341           0 : sal_Bool Connection::isClosed() throw (SQLException, RuntimeException, std::exception)
     342             : {
     343           0 :     return m_settings.pConnection == 0;
     344             : }
     345             : 
     346           0 : Reference< XDatabaseMetaData > Connection::getMetaData()
     347             :         throw (SQLException, RuntimeException, std::exception)
     348             : {
     349           0 :     MutexGuard guard( m_refMutex->mutex );
     350           0 :     checkClosed();
     351           0 :     if( ! m_meta.is() )
     352           0 :         m_meta = new DatabaseMetaData( m_refMutex, this, &m_settings );
     353           0 :     return m_meta;
     354             : }
     355             : 
     356           0 : void  Connection::setReadOnly( sal_Bool ) throw (SQLException, RuntimeException, std::exception)
     357             : {
     358             :     // UNSUPPORTED
     359             : 
     360           0 : }
     361             : 
     362           0 : sal_Bool Connection::isReadOnly() throw (SQLException, RuntimeException, std::exception)
     363             : {
     364             :     // UNSUPPORTED
     365           0 :     return sal_False;
     366             : }
     367             : 
     368           0 : void Connection::setCatalog( const OUString& )
     369             :         throw (SQLException, RuntimeException, std::exception)
     370             : {
     371             :     // UNSUPPORTED
     372           0 : }
     373             : 
     374           0 : OUString Connection::getCatalog() throw (SQLException, RuntimeException, std::exception)
     375             : {
     376           0 :     MutexGuard guard( m_refMutex->mutex );
     377           0 :     if( m_settings.pConnection == 0 )
     378             :     {
     379             :         throw SQLException( "pq_connection: connection is closed", *this,
     380           0 :                             OUString(), 1, Any() );
     381             :     }
     382           0 :     char * p = PQdb(m_settings.pConnection );
     383           0 :     return OUString( p, strlen(p) ,  m_settings.encoding );
     384             : }
     385             : 
     386           0 : void Connection::setTransactionIsolation( sal_Int32 )
     387             :         throw (SQLException, RuntimeException, std::exception)
     388             : {
     389             :     // UNSUPPORTED
     390           0 : }
     391             : 
     392           0 : sal_Int32 Connection::getTransactionIsolation() throw (SQLException, RuntimeException, std::exception)
     393             : {
     394             :     // UNSUPPORTED
     395           0 :     return 0;
     396             : }
     397             : 
     398           0 : Reference< XNameAccess > Connection::getTypeMap() throw (SQLException, RuntimeException, std::exception)
     399             : {
     400           0 :     Reference< XNameAccess > t;
     401             :     {
     402           0 :         MutexGuard guard( m_refMutex->mutex );
     403           0 :         t = m_typeMap;
     404             :     }
     405           0 :     return t;
     406             : }
     407             : 
     408           0 : void Connection::setTypeMap( const Reference< XNameAccess >& typeMap )
     409             :         throw (SQLException, RuntimeException, std::exception)
     410             : {
     411           0 :     MutexGuard guard( m_refMutex->mutex );
     412           0 :     m_typeMap = typeMap;
     413           0 : }
     414           0 : Any Connection::getWarnings() throw (SQLException, RuntimeException, std::exception)
     415             : {
     416           0 :     return Any();
     417             : }
     418             : 
     419           0 : void Connection::clearWarnings() throw (SQLException, RuntimeException, std::exception)
     420             : {
     421           0 : }
     422             : 
     423             : class cstr_vector
     424             : {
     425             :     std::vector<char*> values;
     426             :     std::vector<bool>  acquired;
     427             : public:
     428           0 :     cstr_vector () : values(), acquired() { values.reserve(8); acquired.reserve(8); }
     429           0 :     ~cstr_vector ()
     430           0 :     {
     431             :         OSL_ENSURE(values.size() == acquired.size(), "pq_connection: cstr_vector values and acquired size mismatch");
     432           0 :         std::vector<char*>::iterator pv = values.begin();
     433           0 :         std::vector<bool>::iterator pa = acquired.begin();
     434           0 :         const std::vector<char*>::iterator pve = values.end();
     435           0 :         for( ; pv < pve ; ++pv, ++pa )
     436           0 :             if (*pa)
     437           0 :                 free(*pv);
     438           0 :     }
     439           0 :     void push_back(const char* s, __sal_NoAcquire)
     440             :     {
     441           0 :         values.push_back(const_cast<char*>(s));
     442           0 :         acquired.push_back(false);
     443           0 :     }
     444           0 :     void push_back(char* s)
     445             :     {
     446           0 :         values.push_back(s);
     447           0 :         acquired.push_back(true);
     448           0 :     }
     449             :     // This const_cast is there for compatibility with PostgreSQL <= 9.1;
     450             :     // PostgreSQL >= 9.2 has the right const qualifiers in the headers
     451             :     // for a return type of "char const*const*".
     452           0 :     char const** c_array() const { return const_cast <const char**>(&values[0]); }
     453             : };
     454             : 
     455           0 : static void properties2arrays( const Sequence< PropertyValue > & args,
     456             :                                const Reference< XTypeConverter> &tc,
     457             :                                rtl_TextEncoding enc,
     458             :                                cstr_vector &keywords,
     459             :                                cstr_vector &values)
     460             : {
     461             :     // LEM TODO: can we just blindly take all properties?
     462             :     // I.e. they are prefiltered to have only relevant ones?
     463             :     // Else, at least support all keywords from
     464             :     // http://www.postgresql.org/docs/9.0/interactive/libpq-connect.html
     465             : 
     466             :     static const char* keyword_list[] = {
     467             :         "password",
     468             :         "user",
     469             :         "port",
     470             :         "dbname",
     471             :         "connect_timeout",
     472             :         "options",
     473             :         "requiressl"
     474             :     };
     475             : 
     476           0 :     for( int i = 0; i < args.getLength() ; ++i )
     477             :     {
     478           0 :         bool append = false;
     479           0 :         for( size_t j = 0; j < SAL_N_ELEMENTS( keyword_list ); j++)
     480             :         {
     481           0 :             if( args[i].Name.equalsIgnoreAsciiCaseAscii( keyword_list[j] ))
     482             :             {
     483           0 :                 keywords.push_back( keyword_list[j], SAL_NO_ACQUIRE );
     484           0 :                 append = true;
     485           0 :                 break;
     486             :             }
     487             :         }
     488             : 
     489           0 :         if( append )
     490             :         {
     491           0 :             OUString value;
     492           0 :             tc->convertTo( args[i].Value, getCppuType( &value) ) >>= value;
     493           0 :             char *v = strdup(OUStringToOString(value, enc).getStr());
     494           0 :             values.push_back ( v );
     495             :         }
     496             :         else
     497             :         {
     498             :             // ignore for now
     499             :             OSL_TRACE("sdbc-postgresql: unknown argument '%s'", OUStringToOString( args[i].Name, RTL_TEXTENCODING_UTF8 ).getStr() );
     500             :         }
     501             :     }
     502           0 : }
     503             : 
     504           0 : void Connection::initialize( const Sequence< Any >& aArguments )
     505             :         throw (Exception, RuntimeException, std::exception)
     506             : {
     507           0 :     OUString url;
     508           0 :     Sequence< PropertyValue > args;
     509             : 
     510           0 :     Reference< XTypeConverter > tc( Converter::create(m_ctx) );
     511           0 :     if( ! tc.is() )
     512             :     {
     513             :         throw RuntimeException(
     514           0 :             "pq_driver: Couldn't instantiate converter service" );
     515             :     }
     516           0 :     if( aArguments.getLength() != 2 )
     517             :     {
     518           0 :         OUStringBuffer buf(128);
     519           0 :         buf.appendAscii( "pq_driver: expected 2 arguments, got " );
     520           0 :         buf.append( aArguments.getLength( ) );
     521           0 :         throw IllegalArgumentException(buf.makeStringAndClear(), Reference< XInterface > () , 0 );
     522             :     }
     523             : 
     524           0 :     if( ! (aArguments[0] >>= url) )
     525             :     {
     526           0 :         OUStringBuffer buf(128);
     527           0 :         buf.appendAscii( "pq_driver: expected string as first argument, got " );
     528           0 :         buf.append( aArguments[0].getValueType().getTypeName() );
     529           0 :         throw IllegalArgumentException( buf.makeStringAndClear() , *this, 0 );
     530             :     }
     531             : 
     532           0 :     tc->convertTo( aArguments[1], getCppuType( &args ) ) >>= args;
     533             : 
     534           0 :     OString o;
     535           0 :     int nColon = url.indexOf( ':' );
     536           0 :     if( nColon != -1 )
     537             :     {
     538           0 :         nColon = url.indexOf( ':' , 1+ nColon );
     539           0 :         if( nColon != -1 )
     540             :         {
     541           0 :              o = OUStringToOString( url.getStr()+nColon+1, m_settings.encoding );
     542             :         }
     543             :     }
     544             :     {
     545           0 :         cstr_vector keywords;
     546           0 :         cstr_vector values;
     547             : 
     548           0 :         if ( o.getLength() > 0 )
     549             :         {
     550             :             char *err;
     551           0 :             boost::shared_ptr<PQconninfoOption> oOpts(PQconninfoParse(o.getStr(), &err), PQconninfoFree);
     552           0 :             if ( oOpts.get() == NULL )
     553             :             {
     554           0 :                 OUString errorMessage;
     555           0 :                 if ( err != NULL)
     556             :                 {
     557           0 :                     errorMessage = OUString( err, strlen(err), m_settings.encoding );
     558           0 :                     free(err);
     559             :                 }
     560             :                 else
     561           0 :                     errorMessage = "#no error message#";
     562           0 :                 OUStringBuffer buf( 128 );
     563           0 :                 buf.appendAscii( "Error in database URL '" );
     564           0 :                 buf.append( url );
     565           0 :                 buf.appendAscii( "':\n" );
     566           0 :                 buf.append( errorMessage );
     567             :                 // HY092 is "Invalid attribute/option identifier."
     568             :                 // Just the most likely error; the error might be  HY024 "Invalid attribute value".
     569           0 :                 throw SQLException( buf.makeStringAndClear(), *this, OUString("HY092"), 5, Any() );
     570             :             }
     571             : 
     572           0 :             for (  PQconninfoOption * opt = oOpts.get(); opt->keyword != NULL; ++opt)
     573             :             {
     574           0 :                 if ( opt->val != NULL )
     575             :                 {
     576           0 :                     keywords.push_back(strdup(opt->keyword));
     577           0 :                     values.push_back(strdup(opt->val));
     578             :                 }
     579           0 :             }
     580             :         }
     581           0 :         properties2arrays( args , tc, m_settings.encoding, keywords, values );
     582           0 :         keywords.push_back(NULL, SAL_NO_ACQUIRE);
     583           0 :         values.push_back(NULL, SAL_NO_ACQUIRE);
     584             : 
     585           0 :         m_settings.pConnection = PQconnectdbParams( keywords.c_array(), values.c_array(), 0 );
     586             :     }
     587           0 :     if( ! m_settings.pConnection )
     588           0 :         throw RuntimeException("pq_driver: out of memory" );
     589           0 :     if( PQstatus( m_settings.pConnection ) == CONNECTION_BAD )
     590             :     {
     591           0 :         OUStringBuffer buf( 128 );
     592             : 
     593           0 :         const char * error = PQerrorMessage( m_settings.pConnection );
     594           0 :         OUString errorMessage( error, strlen( error) , RTL_TEXTENCODING_ASCII_US );
     595           0 :         buf.appendAscii( "Couldn't establish database connection to '" );
     596           0 :         buf.append( url );
     597           0 :         buf.appendAscii( "'\n" );
     598           0 :         buf.append( errorMessage );
     599           0 :         PQfinish( m_settings.pConnection );
     600           0 :         m_settings.pConnection = 0;
     601           0 :         throw SQLException( buf.makeStringAndClear(), *this, errorMessage, CONNECTION_BAD, Any() );
     602             :     }
     603           0 :     PQsetClientEncoding( m_settings.pConnection, "UNICODE" );
     604           0 :     char *p = PQuser( m_settings.pConnection );
     605           0 :     m_settings.user = OUString( p, strlen(p), RTL_TEXTENCODING_UTF8);
     606           0 :     p = PQdb( m_settings.pConnection );
     607           0 :     m_settings.catalog = OUString( p, strlen(p), RTL_TEXTENCODING_UTF8);
     608           0 :     m_settings.tc = tc;
     609             : 
     610           0 :     if( isLog( &m_settings, LogLevel::INFO ) )
     611             :     {
     612           0 :         OUStringBuffer buf( 128 );
     613           0 :         buf.appendAscii( "connection to '" );
     614           0 :         buf.append( url );
     615           0 :         buf.appendAscii( "' successfully opened" );
     616           0 :         log( &m_settings, LogLevel::INFO, buf.makeStringAndClear() );
     617           0 :     }
     618           0 : }
     619             : 
     620           0 : void Connection::disposing()
     621             : {
     622           0 :     close();
     623           0 : }
     624             : 
     625           0 : void Connection::checkClosed() throw ( SQLException, RuntimeException )
     626             : {
     627           0 :     if( !m_settings.pConnection )
     628             :         throw SQLException( "pq_connection: Connection already closed",
     629           0 :                             *this, OUString(), 1, Any() );
     630           0 : }
     631             : 
     632           0 : Reference< XNameAccess > Connection::getTables()
     633             :     throw (::com::sun::star::uno::RuntimeException, std::exception)
     634             : {
     635           0 :     if( isLog( &m_settings, LogLevel::INFO ) )
     636             :     {
     637           0 :         log( &m_settings, LogLevel::INFO, "Connection::getTables() got called" );
     638             :     }
     639           0 :     MutexGuard guard( m_refMutex->mutex );
     640           0 :     if( !m_settings.tables.is() )
     641           0 :         m_settings.tables = Tables::create( m_refMutex, this, &m_settings , &m_settings.pTablesImpl);
     642             :     else
     643             :         // TODO: how to overcome the performance problem ?
     644           0 :         Reference< com::sun::star::util::XRefreshable > ( m_settings.tables, UNO_QUERY )->refresh();
     645           0 :     return m_settings.tables;
     646             : }
     647             : 
     648           0 : Reference< XNameAccess > Connection::getViews()
     649             :     throw (::com::sun::star::uno::RuntimeException, std::exception)
     650             : {
     651           0 :     if( isLog( &m_settings, LogLevel::INFO ) )
     652             :     {
     653           0 :         log( &m_settings, LogLevel::INFO, "Connection::getViews() got called" );
     654             :     }
     655           0 :     MutexGuard guard( m_refMutex->mutex );
     656           0 :     if( !m_settings.views.is() )
     657           0 :         m_settings.views = Views::create( m_refMutex, this, &m_settings, &(m_settings.pViewsImpl) );
     658             :     else
     659             :         // TODO: how to overcome the performance problem ?
     660           0 :         Reference< com::sun::star::util::XRefreshable > ( m_settings.views, UNO_QUERY )->refresh();
     661           0 :     return m_settings.views;
     662             : }
     663             : 
     664             : 
     665             : 
     666           0 : Reference< XNameAccess > Connection::getUsers()
     667             :     throw (::com::sun::star::uno::RuntimeException, std::exception)
     668             : {
     669           0 :     if( isLog( &m_settings, LogLevel::INFO ) )
     670             :     {
     671           0 :         log( &m_settings, LogLevel::INFO, "Connection::getUsers() got called" );
     672             :     }
     673             : 
     674           0 :     MutexGuard guard( m_refMutex->mutex );
     675           0 :     if( !m_settings.users.is() )
     676           0 :         m_settings.users = Users::create( m_refMutex, this, &m_settings );
     677           0 :     return m_settings.users;
     678             : }
     679             : 
     680             : 
     681           0 : Reference< XInterface >  ConnectionCreateInstance(
     682             :     const Reference< XComponentContext > & ctx ) throw (Exception)
     683             : {
     684           0 :     ::rtl::Reference< RefCountedMutex > ref = new RefCountedMutex();
     685           0 :     return * new Connection( ref, ctx );
     686             : }
     687             : 
     688             : 
     689             : 
     690           0 : bool isLog( ConnectionSettings *settings, int loglevel )
     691             : {
     692           0 :     return settings->loglevel >= loglevel && settings->logFile;
     693             : }
     694             : 
     695           0 : void log( ConnectionSettings *settings, sal_Int32 level, const OUString &logString )
     696             : {
     697           0 :     log( settings, level, OUStringToOString( logString, settings->encoding ).getStr() );
     698           0 : }
     699           0 : void log( ConnectionSettings *settings, sal_Int32 level, const char *str )
     700             : {
     701           0 :     if( isLog( settings, level ) )
     702             :     {
     703             :         static const char *strLevel[] = { "NONE", "ERROR", "SQL", "INFO", "DATA" };
     704             : 
     705           0 :         time_t t = ::time( 0 );
     706             :         char *pString;
     707             : #ifdef SAL_W32
     708             :         pString = asctime( localtime( &t ) );
     709             : #else
     710             :         struct tm timestruc;
     711             :         char timestr[50];
     712           0 :         memset( timestr, 0 , 50);
     713           0 :         pString = timestr;
     714           0 :         ::localtime_r( &t , &timestruc );
     715           0 :         asctime_r( &timestruc, timestr );
     716             : #endif
     717           0 :         for( int i = 0 ; pString[i] ; i ++ )
     718             :         {
     719           0 :             if( pString[i] <= 13 )
     720             :             {
     721           0 :                 pString[i] = 0;
     722           0 :                 break;
     723             :             }
     724             :         }
     725           0 :         fprintf( settings->logFile, "%s [%s]: %s\n", pString, strLevel[level], str );
     726             :     }
     727           0 : }
     728             : 
     729             : 
     730             : }
     731             : 
     732             : 
     733             : 
     734             : static const struct cppu::ImplementationEntry g_entries[] =
     735             : {
     736             :     {
     737             :         pq_sdbc_driver::ConnectionCreateInstance, pq_sdbc_driver::ConnectionGetImplementationName,
     738             :         pq_sdbc_driver::ConnectionGetSupportedServiceNames, cppu::createSingleComponentFactory,
     739             :         0 , 0
     740             :     },
     741             :     { 0, 0, 0, 0, 0, 0 }
     742             : };
     743             : 
     744             : 
     745             : extern "C"
     746             : {
     747             : 
     748           0 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL postgresql_sdbc_impl_component_getFactory(
     749             :     const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
     750             : {
     751           0 :     return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
     752             : }
     753             : 
     754             : }
     755             : 
     756             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10