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

Generated by: LCOV version 1.10