LCOV - code coverage report
Current view: top level - connectivity/source/drivers/postgresql - pq_resultsetmetadata.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 182 0.0 %
Date: 2014-04-14 Functions: 0 30 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 <rtl/ustrbuf.hxx>
      38             : 
      39             : #include "pq_resultsetmetadata.hxx"
      40             : #include "pq_resultset.hxx"
      41             : #include "pq_tools.hxx"
      42             : #include "pq_statics.hxx"
      43             : 
      44             : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
      45             : #include <com/sun/star/sdbc/ColumnValue.hpp>
      46             : #include <com/sun/star/sdbc/XRow.hpp>
      47             : 
      48             : #include <string.h>
      49             : 
      50             : using osl::Mutex;
      51             : using osl::MutexGuard;
      52             : 
      53             : 
      54             : using com::sun::star::uno::Any;
      55             : using com::sun::star::uno::RuntimeException;
      56             : using com::sun::star::uno::Exception;
      57             : using com::sun::star::uno::Reference;
      58             : using com::sun::star::uno::XInterface;
      59             : using com::sun::star::uno::UNO_QUERY;
      60             : 
      61             : using com::sun::star::lang::IllegalArgumentException;
      62             : 
      63             : using com::sun::star::sdbc::SQLException;
      64             : using com::sun::star::sdbc::XStatement;
      65             : using com::sun::star::sdbc::XRow;
      66             : using com::sun::star::sdbc::XResultSet;
      67             : using com::sun::star::sdbcx::XColumnsSupplier;
      68             : using com::sun::star::sdbcx::XTablesSupplier;
      69             : 
      70             : using com::sun::star::beans::XPropertySet;
      71             : using com::sun::star::container::XNameAccess;
      72             : 
      73             : 
      74             : namespace pq_sdbc_driver
      75             : {
      76             : 
      77             : // struct ColumnMetaData
      78             : // {
      79             : //     OUString tableName;
      80             : //     OUString schemaTableName;
      81             : //     OUString typeName;
      82             : //     com::sun::star::sdbc::DataType type;
      83             : //     sal_Int32 precision;
      84             : //     sal_Int32 scale;
      85             : //     sal_Bool isCurrency;
      86             : //     sal_Bool isNullable;
      87             : //     sal_Bool isAutoIncrement;
      88             : //     sal_Bool isReadOnly;
      89             : //     sal_Bool isSigned;
      90             : // };
      91             : 
      92             : // is not exported by the postgres header
      93             : const static int PQ_VARHDRSZ = sizeof( sal_Int32 );
      94             : 
      95           0 : static void extractPrecisionAndScale( sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
      96             : {
      97           0 :     if( atttypmod < PQ_VARHDRSZ )
      98             :     {
      99           0 :         *precision = 0;
     100           0 :         *scale = 0;
     101             :     }
     102             :     else
     103             :     {
     104           0 :         if( atttypmod & 0xffff0000 )
     105             :         {
     106           0 :             *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
     107           0 :             *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
     108             :         }
     109             :         else
     110             :         {
     111           0 :             *precision = atttypmod - PQ_VARHDRSZ;
     112           0 :             *scale = 0;
     113             :         }
     114             :     }
     115           0 : }
     116             : 
     117           0 : ResultSetMetaData::ResultSetMetaData(
     118             :     const ::rtl::Reference< RefCountedMutex > & refMutex,
     119             :     const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet >  & origin,
     120             :     ResultSet * pResultSet,
     121             :     ConnectionSettings **ppSettings,
     122             :     PGresult *pResult,
     123             :     const OUString &schemaName,
     124             :     const OUString &tableName ) :
     125             :     m_refMutex( refMutex ),
     126             :     m_ppSettings( ppSettings ),
     127             :     m_origin( origin ),
     128             :     m_tableName( tableName ),
     129             :     m_schemaName( schemaName ),
     130           0 :     m_colDesc( PQnfields( pResult ) ),
     131             :     m_pResultSet( pResultSet ),
     132             :     m_checkedForTable( false ),
     133             :     m_checkedForTypes( false ),
     134           0 :     m_colCount( PQnfields( pResult ) )
     135             : {
     136             : 
     137             :     // extract all needed information from the result object, so that we don't
     138             :     // need it anymore after this call !
     139           0 :     for( int col = 0; col < m_colCount ; col ++ )
     140             :     {
     141           0 :         sal_Int32 size = PQfsize( pResult, col );
     142           0 :         size = -1 == size ? 25 : size;
     143           0 :         m_colDesc[col].displaySize = size;
     144             : 
     145             :         extractPrecisionAndScale(
     146           0 :             PQfmod( pResult, col ),
     147           0 :             & ( m_colDesc[col].precision ),
     148           0 :             & ( m_colDesc[col].scale ) );
     149           0 :         char *name = PQfname( pResult, col );
     150           0 :         m_colDesc[col].name = OUString( name, strlen(name) , (*m_ppSettings)->encoding );
     151           0 :         m_colDesc[col].typeOid = PQftype( pResult, col );
     152           0 :         m_colDesc[col].type = com::sun::star::sdbc::DataType::LONGVARCHAR;
     153             :     }
     154           0 : }
     155             : 
     156           0 : void ResultSetMetaData::checkForTypes()
     157             : {
     158           0 :     if( ! m_checkedForTypes )
     159             :     {
     160             :         Reference< XStatement > stmt =
     161           0 :             extractConnectionFromStatement( m_origin->getStatement() )->createStatement();
     162           0 :         DisposeGuard guard( stmt );
     163           0 :         OUStringBuffer buf(128);
     164           0 :         buf.appendAscii( "SELECT oid, typname, typtype FROM pg_type WHERE ");
     165           0 :         for( int i  = 0 ; i < m_colCount ; i ++ )
     166             :         {
     167           0 :             if( i > 0 )
     168           0 :                 buf.appendAscii( " OR " );
     169           0 :             int oid = m_colDesc[i].typeOid;
     170           0 :             buf.appendAscii( "oid=" );
     171           0 :             buf.append( (sal_Int32) oid, 10 );
     172             :         }
     173           0 :         Reference< XResultSet > rs = stmt->executeQuery( buf.makeStringAndClear() );
     174           0 :         Reference< XRow > xRow( rs, UNO_QUERY );
     175           0 :         while( rs->next() )
     176             :         {
     177           0 :             Oid oid = xRow->getInt( 1 );
     178           0 :             OUString typeName = xRow->getString( 2 );
     179           0 :             OUString typType = xRow->getString( 3 );
     180             : 
     181           0 :             sal_Int32 type = typeNameToDataType( typeName, typType );
     182             : 
     183           0 :             for( sal_Int32 j = 0; j < m_colCount ; j ++ )
     184             :             {
     185           0 :                 if( m_colDesc[j].typeOid == oid )
     186             :                 {
     187           0 :                     m_colDesc[j].typeName = typeName;
     188           0 :                     m_colDesc[j].type = type;
     189             :                 }
     190             :             }
     191           0 :         }
     192           0 :         m_checkedForTypes = true;
     193             :     }
     194           0 : }
     195             : 
     196           0 : void ResultSetMetaData::checkTable()
     197             : {
     198           0 :     if( ! m_checkedForTable )
     199             :     {
     200           0 :         m_checkedForTable = true;
     201           0 :         if( m_tableName.getLength() )
     202             :         {
     203             : 
     204           0 :             Reference< com::sun::star::container::XNameAccess > tables = (*m_ppSettings)->tables;
     205           0 :             if( ! tables.is() )
     206             :             {
     207             : 
     208             :                 Reference< XTablesSupplier > supplier =
     209             :                     Reference< XTablesSupplier > (
     210           0 :                         extractConnectionFromStatement( m_origin->getStatement() ), UNO_QUERY);
     211           0 :                 if( supplier.is() )
     212           0 :                     tables = supplier->getTables();
     213             :             }
     214           0 :             if( tables.is() )
     215             :             {
     216           0 :                 const OUString name   (getTableName ( 1 ));
     217           0 :                 const OUString schema (getSchemaName( 1 ));
     218           0 :                 const OUString composedName( schema.isEmpty() ? name : (schema + "." + name) );
     219           0 :                 tables->getByName( composedName ) >>= m_table;
     220           0 :             }
     221             :         }
     222             :     }
     223           0 : }
     224             : 
     225           0 : sal_Int32 ResultSetMetaData::getIntColumnProperty( const OUString & name, int index, int def )
     226             : {
     227           0 :     sal_Int32 ret = def; // give defensive answers, when data is not available
     228             :     try
     229             :     {
     230           0 :         MutexGuard guard( m_refMutex->mutex );
     231           0 :         checkColumnIndex( index );
     232           0 :         Reference< XPropertySet > set = getColumnByIndex( index );
     233             : 
     234           0 :         if( set.is() )
     235             :         {
     236           0 :             set->getPropertyValue( name ) >>= ret;
     237           0 :         }
     238             :     }
     239           0 :     catch( com::sun::star::uno::Exception & )
     240             :     {
     241             :     }
     242           0 :     return ret;
     243             : }
     244             : 
     245           0 : sal_Bool ResultSetMetaData::getBoolColumnProperty( const OUString & name, int index, sal_Bool def )
     246             : {
     247           0 :     sal_Bool ret = def;
     248             :     try
     249             :     {
     250           0 :         MutexGuard guard( m_refMutex->mutex );
     251           0 :         checkColumnIndex( index );
     252           0 :         Reference< XPropertySet > set = getColumnByIndex( index );
     253           0 :         if( set.is() )
     254             :         {
     255           0 :             set->getPropertyValue( name ) >>= ret;
     256           0 :         }
     257             :     }
     258           0 :     catch( com::sun::star::uno::Exception & )
     259             :     {
     260             :     }
     261             : 
     262           0 :     return ret;
     263             : }
     264             : 
     265           0 : Reference< com::sun::star::beans::XPropertySet > ResultSetMetaData::getColumnByIndex( int index )
     266             : {
     267           0 :     Reference< XPropertySet > ret;
     268           0 :     checkTable();
     269           0 :     if( m_table.is() )
     270             :     {
     271           0 :         OUString columnName = getColumnName( index );
     272           0 :         Reference< XColumnsSupplier > supplier( m_table, UNO_QUERY );
     273           0 :         if( supplier.is() )
     274             :         {
     275           0 :             Reference< XNameAccess > columns = supplier->getColumns();
     276           0 :             if( columns.is() && columns->hasByName( columnName ) )
     277             :             {
     278           0 :                 columns->getByName( columnName ) >>= ret;
     279           0 :             }
     280           0 :         }
     281             :     }
     282           0 :     return ret;
     283             : }
     284             : 
     285             : // Methods
     286           0 : sal_Int32 ResultSetMetaData::getColumnCount(  )
     287             :     throw (SQLException, RuntimeException, std::exception)
     288             : {
     289           0 :     return m_colCount;
     290             : }
     291             : 
     292           0 : sal_Bool ResultSetMetaData::isAutoIncrement( sal_Int32 column )
     293             :     throw (SQLException, RuntimeException, std::exception)
     294             : {
     295             : 
     296           0 :     sal_Bool ret = getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT, column, sal_False );
     297           0 :     return ret;
     298             : }
     299             : 
     300           0 : sal_Bool ResultSetMetaData::isCaseSensitive( sal_Int32 column )
     301             :     throw (SQLException, RuntimeException, std::exception)
     302             : {
     303             :     (void) column;
     304           0 :     return sal_True; // ??? hmm, numeric types or
     305             : }
     306             : 
     307           0 : sal_Bool ResultSetMetaData::isSearchable( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
     308             : {
     309             :     (void) column;
     310           0 :     return sal_True; // mmm, what types are not searchable ?
     311             : }
     312             : 
     313           0 : sal_Bool ResultSetMetaData::isCurrency( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
     314             : {
     315           0 :     return getBoolColumnProperty( getStatics().IS_CURRENCY, column, sal_False );
     316             : }
     317             : 
     318           0 : sal_Int32 ResultSetMetaData::isNullable( sal_Int32 column )
     319             :     throw (SQLException, RuntimeException, std::exception)
     320             : {
     321             :     return getIntColumnProperty(
     322           0 :         getStatics().IS_NULLABLE, column, com::sun::star::sdbc::ColumnValue::NULLABLE_UNKNOWN );
     323             : }
     324             : 
     325           0 : sal_Bool ResultSetMetaData::isSigned( sal_Int32 column )
     326             :     throw (SQLException, RuntimeException, std::exception)
     327             : {
     328             :     (void) column;
     329           0 :     return sal_True;
     330             : }
     331             : 
     332           0 : sal_Int32 ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
     333             :     throw (SQLException, RuntimeException, std::exception)
     334             : {
     335           0 :     MutexGuard guard( m_refMutex->mutex );
     336           0 :     checkClosed();
     337           0 :     checkColumnIndex( column );
     338           0 :     return m_colDesc[column-1].displaySize;
     339             : }
     340             : 
     341           0 : OUString ResultSetMetaData::getColumnLabel( sal_Int32 column )
     342             :     throw (SQLException, RuntimeException, std::exception)
     343             : {
     344           0 :     return getColumnName( column);
     345             : }
     346             : 
     347           0 : OUString ResultSetMetaData::getColumnName( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
     348             : {
     349           0 :     MutexGuard guard( m_refMutex->mutex );
     350           0 :     checkClosed();
     351           0 :     checkColumnIndex( column );
     352             : 
     353           0 :     return m_colDesc[column-1].name;
     354             : }
     355             : 
     356           0 : OUString ResultSetMetaData::getSchemaName( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
     357             : {
     358             :     (void) column;
     359           0 :     return m_schemaName;
     360             : }
     361             : 
     362           0 : sal_Int32 ResultSetMetaData::getPrecision( sal_Int32 column )
     363             :     throw (SQLException, RuntimeException, std::exception)
     364             : {
     365           0 :     MutexGuard guard( m_refMutex->mutex );
     366           0 :     checkClosed();
     367           0 :     checkColumnIndex( column );
     368           0 :     return m_colDesc[column-1].precision;
     369             : }
     370             : 
     371           0 : sal_Int32 ResultSetMetaData::getScale( sal_Int32 column )
     372             :     throw (SQLException, RuntimeException, std::exception)
     373             : {
     374           0 :     MutexGuard guard( m_refMutex->mutex );
     375           0 :     checkClosed();
     376           0 :     checkColumnIndex( column );
     377           0 :     return m_colDesc[column-1].scale;
     378             : }
     379             : 
     380           0 : OUString ResultSetMetaData::getTableName( sal_Int32 column )
     381             :     throw (SQLException, RuntimeException, std::exception)
     382             : {
     383             :     (void) column;
     384             : // LEM TODO This is very fishy.. Should probably return the table to which that column belongs!
     385           0 :     return m_tableName;
     386             : }
     387             : 
     388           0 : OUString ResultSetMetaData::getCatalogName( sal_Int32 column )
     389             :     throw (SQLException, RuntimeException, std::exception)
     390             : {
     391             :     (void) column;
     392             :     // can do this through XConnection.getCatalog() !
     393           0 :     return OUString();
     394             : }
     395           0 : sal_Int32 ResultSetMetaData::getColumnType( sal_Int32 column )
     396             :     throw (SQLException, RuntimeException, std::exception)
     397             : {
     398           0 :     int ret = getIntColumnProperty( getStatics().TYPE, column, -100 );
     399           0 :     if( -100 == ret )
     400             :     {
     401           0 :         checkForTypes();
     402           0 :         if( com::sun::star::sdbc::DataType::LONGVARCHAR == m_colDesc[column-1].type && m_pResultSet )
     403           0 :             m_colDesc[column-1].type = m_pResultSet->guessDataType( column );
     404           0 :         ret = m_colDesc[column-1].type;
     405             :     }
     406           0 :     return ret;
     407             : }
     408             : 
     409           0 : OUString ResultSetMetaData::getColumnTypeName( sal_Int32 column )
     410             :     throw (SQLException, RuntimeException, std::exception)
     411             : {
     412           0 :     OUString ret; // give defensive answers, when data is not available
     413             :     try
     414             :     {
     415           0 :         MutexGuard guard( m_refMutex->mutex );
     416           0 :         checkColumnIndex( column );
     417           0 :         Reference< XPropertySet > set = getColumnByIndex( column );
     418             : 
     419           0 :         if( set.is() )
     420             :         {
     421           0 :             set->getPropertyValue( getStatics().TYPE_NAME ) >>= ret;
     422             :         }
     423             :         else
     424             :         {
     425           0 :             checkForTypes();
     426           0 :             ret = m_colDesc[column-1].typeName;
     427           0 :         }
     428             :     }
     429           0 :     catch( com::sun::star::uno::Exception & )
     430             :     {
     431             :     }
     432           0 :     return ret;
     433             : }
     434             : 
     435             : 
     436           0 : sal_Bool ResultSetMetaData::isReadOnly( sal_Int32 column )
     437             :     throw (SQLException, RuntimeException, std::exception)
     438             : {
     439             :     (void) column;
     440           0 :     return sal_False;
     441             : }
     442             : 
     443           0 : sal_Bool ResultSetMetaData::isWritable( sal_Int32 column )
     444             :     throw (SQLException, RuntimeException, std::exception)
     445             : {
     446           0 :     return ! isReadOnly( column ); // what's the sense if this method ?
     447             : }
     448             : 
     449           0 : sal_Bool ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
     450             :     throw (SQLException, RuntimeException, std::exception)
     451             : {
     452           0 :     return isWritable(column); // uhh, now it becomes really esoteric ....
     453             : }
     454           0 : OUString ResultSetMetaData::getColumnServiceName( sal_Int32 column )
     455             :     throw (SQLException, RuntimeException, std::exception)
     456             : {
     457             :     (void) column;
     458           0 :     return OUString();
     459             : }
     460             : 
     461           0 : void ResultSetMetaData::checkClosed()
     462             :     throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
     463             : {
     464             :     // we never close
     465           0 : }
     466             : 
     467           0 : void ResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
     468             :     throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
     469             : {
     470           0 :     if( columnIndex < 1 || columnIndex > m_colCount )
     471             :     {
     472           0 :         OUStringBuffer buf(128);
     473             : 
     474           0 :         buf.appendAscii( "pq_resultsetmetadata: index out of range (expected 1 to " );
     475           0 :         buf.append( m_colCount );
     476           0 :         buf.appendAscii( ", got " );
     477           0 :         buf.append( columnIndex );
     478             :         throw SQLException(
     479           0 :             buf.makeStringAndClear(), *this, OUString(), 1, Any() );
     480             :     }
     481           0 : }
     482             : 
     483             : }
     484             : 
     485             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10