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

Generated by: LCOV version 1.10