LCOV - code coverage report
Current view: top level - connectivity/source/drivers/postgresql - pq_resultset.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 121 0.0 %
Date: 2014-04-14 Functions: 0 14 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 "pq_resultset.hxx"
      38             : #include "pq_resultsetmetadata.hxx"
      39             : 
      40             : #include <connectivity/dbexception.hxx>
      41             : 
      42             : #include <com/sun/star/sdbc/FetchDirection.hpp>
      43             : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
      44             : #include <com/sun/star/sdbc/ResultSetType.hpp>
      45             : #include <com/sun/star/sdbc/DataType.hpp>
      46             : 
      47             : 
      48             : using osl::MutexGuard;
      49             : 
      50             : using com::sun::star::uno::RuntimeException;
      51             : using com::sun::star::uno::Any;
      52             : using com::sun::star::uno::makeAny;
      53             : using com::sun::star::uno::Reference;
      54             : using com::sun::star::uno::XInterface;
      55             : 
      56             : using com::sun::star::sdbc::SQLException;
      57             : using com::sun::star::sdbc::XResultSetMetaData;
      58             : 
      59             : 
      60             : namespace pq_sdbc_driver
      61             : {
      62             : 
      63           0 : void ResultSet::checkClosed()
      64             :     throw ( com::sun::star::sdbc::SQLException, com::sun::star::uno::RuntimeException )
      65             : {
      66           0 :     if( ! m_result )
      67             :     {
      68             :         throw SQLException( "pq_resultset: already closed",
      69           0 :                             *this,  OUString(), 1, Any() );
      70             :     }
      71             : 
      72           0 :     if( ! m_ppSettings || ! *m_ppSettings || ! (*m_ppSettings)->pConnection )
      73             :     {
      74             :         throw SQLException( "pq_resultset: statement has been closed already",
      75           0 :                             *this, OUString(), 1, Any() );
      76             :     }
      77             : 
      78           0 : }
      79             : 
      80           0 : ResultSet::ResultSet( const ::rtl::Reference< RefCountedMutex > & refMutex,
      81             :                       const Reference< XInterface > & owner,
      82             :                       ConnectionSettings **ppSettings,
      83             :                       PGresult * result,
      84             :                       const OUString &schema,
      85             :                       const OUString &table)
      86             :     : BaseResultSet(
      87           0 :         refMutex, owner, PQntuples( result ),
      88           0 :         PQnfields( result ),(*ppSettings)->tc ),
      89             :       m_result( result ),
      90             :       m_schema( schema ),
      91             :       m_table( table ),
      92           0 :       m_ppSettings( ppSettings )
      93             : {
      94             :     // LEM TODO: shouldn't these things be inherited from the statement or something like that?
      95           0 :     sal_Bool b = sal_False;
      96             :     // Positioned update/delete not supported, so no cursor name
      97             :     // Fetch direction and size are cursor-specific things, so not used now.
      98             :     // Fetch size not set
      99           0 :     m_props[ BASERESULTSET_FETCH_DIRECTION ] = makeAny(
     100           0 :         com::sun::star::sdbc::FetchDirection::UNKNOWN);
     101             :     // No escape processing for now
     102           0 :     m_props[ BASERESULTSET_ESCAPE_PROCESSING ] = Any( &b, getBooleanCppuType() );
     103             :     // Bookmarks not implemented for now
     104           0 :     m_props[ BASERESULTSET_IS_BOOKMARKABLE ] = Any( &b, getBooleanCppuType() );
     105           0 :     m_props[ BASERESULTSET_RESULT_SET_CONCURRENCY ] = makeAny(
     106           0 :         com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY );
     107           0 :     m_props[ BASERESULTSET_RESULT_SET_TYPE ] = makeAny(
     108           0 :         com::sun::star::sdbc::ResultSetType::SCROLL_INSENSITIVE );
     109           0 : }
     110             : 
     111             : 
     112           0 : Any ResultSet::getValue( sal_Int32 columnIndex )
     113             : {
     114           0 :     Any ret;
     115           0 :     if( PQgetisnull( m_result, m_row, columnIndex -1 ) )
     116             :     {
     117           0 :         m_wasNull = true;
     118             :     }
     119             :     else
     120             :     {
     121           0 :         m_wasNull = false;
     122           0 :         ret <<= OUString(
     123           0 :             PQgetvalue( m_result, m_row , columnIndex -1 ) ,
     124           0 :             PQgetlength( m_result, m_row , columnIndex -1 ) ,
     125           0 :             (*m_ppSettings)->encoding );
     126             : 
     127             :     }
     128           0 :     return ret;
     129             : }
     130             : 
     131           0 : ResultSet::~ResultSet()
     132           0 : {}
     133             : 
     134           0 : void ResultSet::close(  ) throw (SQLException, RuntimeException, std::exception)
     135             : {
     136           0 :     Reference< XInterface > owner;
     137             :     {
     138           0 :         MutexGuard guard( m_refMutex->mutex );
     139           0 :         if( m_result )
     140             :         {
     141           0 :             PQclear(m_result );
     142           0 :             m_result = 0;
     143           0 :             m_row = -1;
     144             :         }
     145           0 :         owner = m_owner;
     146           0 :         m_owner.clear();
     147           0 :     }
     148           0 : }
     149             : 
     150           0 : Reference< XResultSetMetaData > ResultSet::getMetaData(  ) throw (SQLException, RuntimeException, std::exception)
     151             : {
     152           0 :     MutexGuard guard( m_refMutex->mutex );
     153           0 :     checkClosed();
     154             :     return new ResultSetMetaData(
     155           0 :         m_refMutex, this, this, m_ppSettings, m_result, m_schema, m_table );
     156             : }
     157             : 
     158           0 : sal_Int32 ResultSet::findColumn( const OUString& columnName )
     159             :         throw (SQLException, RuntimeException, std::exception)
     160             : {
     161           0 :     MutexGuard guard( m_refMutex->mutex );
     162           0 :     checkClosed();
     163             :     sal_Int32 res = PQfnumber( m_result,
     164           0 :                                OUStringToOString( columnName, (*m_ppSettings)->encoding ).getStr());
     165             :     /* PQfnumber reurn -1 for not found, which is waht we want
     166             :      * otehr than that we use col number as 1-based not 0-based */
     167           0 :     if(res >= 0)
     168             :     {
     169           0 :         res += 1;
     170             :     }
     171             :     else
     172             :     {
     173           0 :         ::dbtools::throwInvalidColumnException( columnName, *this );
     174             :         assert(false);
     175             :     }
     176           0 :     return res;
     177             : }
     178             : 
     179           0 : static bool isNumber( const char * data, sal_Int32 len )
     180             : {
     181           0 :     bool ret = false;
     182           0 :     if( len )
     183             :     {
     184           0 :         ret = true;
     185           0 :         for( int i = 0 ; i < len ; i ++ )
     186             :         {
     187           0 :             if( ( data[i] >= '0' && data[i] <= '9' ) ||
     188           0 :                 data[i] == '-' || data[i] == '+' || data[i] == '.' || data[i] == ',' )
     189             :             {
     190           0 :                 if( data[i] == '-' && i != 0 && i != len-1 )
     191             :                 {
     192             :                     // no number, maybe a date
     193           0 :                     ret = false;
     194           0 :                     break;
     195             :                 }
     196             :             }
     197             :             else
     198             :             {
     199           0 :                 ret = false;
     200           0 :                 break;
     201             :             }
     202             :         }
     203             :     }
     204           0 :     return ret;
     205             : }
     206             : 
     207           0 : static bool isInteger( const char * data, sal_Int32 len )
     208             : {
     209           0 :     bool ret = false;
     210           0 :     if( len )
     211             :     {
     212           0 :         ret = true;
     213           0 :         for( int i = 0 ; i < len ; i ++ )
     214             :         {
     215           0 :             if( ( data[i] >= '0' && data[i] <= '9' ) ||
     216           0 :                 data[i] == '-' || data[i] == '+' )
     217             :             {
     218           0 :                 if( data[i] == '-' && i != 0 && i != len-1 )
     219             :                 {
     220             :                     // no number, maybe a date
     221           0 :                     ret = false;
     222           0 :                     break;
     223             :                 }
     224             :             }
     225             :             else
     226             :             {
     227           0 :                 ret = false;
     228           0 :                 break;
     229             :             }
     230             :         }
     231             :     }
     232           0 :     return ret;
     233             : }
     234             : 
     235           0 : static bool isDate( const char * data, sal_Int32 len )
     236             : {
     237           0 :     return 10 == len &&
     238           0 :         '-' == data[4] &&
     239           0 :         '-' == data[7] &&
     240           0 :         isInteger( &(data[0]),4 ) &&
     241           0 :         isInteger( &(data[5]),2) &&
     242           0 :         isInteger( &(data[8]),2 );
     243             : }
     244             : 
     245           0 : static bool isTime( const char * data, sal_Int32 len )
     246             : {
     247           0 :     return 8 == len &&
     248           0 :         ':' == data[2] &&
     249           0 :         ':' == data[5] &&
     250           0 :         isInteger( &(data[0]),2 ) &&
     251           0 :         isInteger( &(data[3]),2) &&
     252           0 :         isInteger( &(data[6]),2 );
     253             : 
     254             : }
     255             : 
     256           0 : static bool isTimestamp( const char * data, sal_Int32 len )
     257             : {
     258           0 :     return len == 19 && isDate( data, 10) && isTime( &(data[11]),8 );
     259             : }
     260             : 
     261           0 : sal_Int32 ResultSet::guessDataType( sal_Int32 column )
     262             : {
     263             :     // we don't look into more than 100 rows ...
     264           0 :     sal_Int32 ret = com::sun::star::sdbc::DataType::INTEGER;
     265             : 
     266           0 :     int maxRows = ( m_rowCount > 100 ? 100 : m_rowCount );
     267           0 :     for( int i = 0 ; i < maxRows ; i ++ )
     268             :     {
     269           0 :         if( ! PQgetisnull( m_result, i , column-1  ) )
     270             :         {
     271           0 :             const char * p = PQgetvalue( m_result, i , column -1 );
     272           0 :             int len = PQgetlength( m_result, i , column -1 );
     273             : 
     274           0 :             if( com::sun::star::sdbc::DataType::INTEGER == ret )
     275             :             {
     276           0 :                 if( ! isInteger( p,len ) )
     277           0 :                     ret = com::sun::star::sdbc::DataType::NUMERIC;
     278             :             }
     279           0 :             if( com::sun::star::sdbc::DataType::NUMERIC == ret )
     280             :             {
     281           0 :                 if( ! isNumber( p,len ) )
     282             :                 {
     283           0 :                     ret = com::sun::star::sdbc::DataType::DATE;
     284             :                 }
     285             :             }
     286           0 :             if( com::sun::star::sdbc::DataType::DATE == ret )
     287             :             {
     288           0 :                 if( ! isDate( p,len ) )
     289             :                 {
     290           0 :                     ret = com::sun::star::sdbc::DataType::TIME;
     291             :                 }
     292             :             }
     293           0 :             if( com::sun::star::sdbc::DataType::TIME == ret )
     294             :             {
     295           0 :                 if( ! isTime( p,len ) )
     296             :                 {
     297           0 :                     ret = com::sun::star::sdbc::DataType::TIMESTAMP;
     298             :                 }
     299             :             }
     300           0 :             if( com::sun::star::sdbc::DataType::TIMESTAMP == ret )
     301             :             {
     302           0 :                 if( ! isTimestamp( p,len ) )
     303             :                 {
     304           0 :                     ret = com::sun::star::sdbc::DataType::LONGVARCHAR;
     305           0 :                     break;
     306             :                 }
     307             :             }
     308             :         }
     309             :     }
     310           0 :     return ret;
     311             : }
     312             : 
     313             : }
     314             : 
     315             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10