Update ooo320-m1
[ooovba.git] / connectivity / source / drivers / postgresql / pq_resultsetmetadata.cxx
blob31dae4ae8741f18c21208ed4db5683448f998cc1
1 /*************************************************************************
3 * $RCSfile: pq_resultsetmetadata.cxx,v $
5 * $Revision: 1.1.2.7 $
7 * last change: $Author: jbu $ $Date: 2006/05/27 11:32:13 $
9 * The Contents of this file are made available subject to the terms of
10 * either of the following licenses
12 * - GNU Lesser General Public License Version 2.1
13 * - Sun Industry Standards Source License Version 1.1
15 * Sun Microsystems Inc., October, 2000
17 * GNU Lesser General Public License Version 2.1
18 * =============================================
19 * Copyright 2000 by Sun Microsystems, Inc.
20 * 901 San Antonio Road, Palo Alto, CA 94303, USA
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License version 2.1, as published by the Free Software Foundation.
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 * MA 02111-1307 USA
37 * Sun Industry Standards Source License Version 1.1
38 * =================================================
39 * The contents of this file are subject to the Sun Industry Standards
40 * Source License Version 1.1 (the "License"); You may not use this file
41 * except in compliance with the License. You may obtain a copy of the
42 * License at http://www.openoffice.org/license.html.
44 * Software provided under this License is provided on an "AS IS" basis,
45 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
46 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
47 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
48 * See the License for the specific provisions governing your rights and
49 * obligations concerning the Software.
51 * The Initial Developer of the Original Code is: Joerg Budischewski
53 * Copyright: 2000 by Sun Microsystems, Inc.
55 * All Rights Reserved.
57 * Contributor(s): Joerg Budischewski
60 ************************************************************************/
61 #include <rtl/ustrbuf.hxx>
63 #include "pq_resultsetmetadata.hxx"
64 #include "pq_resultset.hxx"
65 #include "pq_tools.hxx"
66 #include "pq_statics.hxx"
68 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
69 #include <com/sun/star/sdbc/ColumnValue.hpp>
70 #include <com/sun/star/sdbc/XRow.hpp>
72 #include <string.h>
74 using osl::Mutex;
75 using osl::MutexGuard;
77 using rtl::OUString;
78 using rtl::OUStringBuffer;
79 using rtl::OString;
81 using com::sun::star::uno::Any;
82 using com::sun::star::uno::RuntimeException;
83 using com::sun::star::uno::Exception;
84 using com::sun::star::uno::Reference;
85 using com::sun::star::uno::XInterface;
86 using com::sun::star::uno::UNO_QUERY;
88 using com::sun::star::lang::IllegalArgumentException;
90 using com::sun::star::sdbc::SQLException;
91 using com::sun::star::sdbc::XStatement;
92 using com::sun::star::sdbc::XRow;
93 using com::sun::star::sdbc::XResultSet;
94 // using com::sun::star::sdbc::XRow;
95 using com::sun::star::sdbc::XResultSet;
96 using com::sun::star::sdbcx::XColumnsSupplier;
97 using com::sun::star::sdbcx::XTablesSupplier;
99 using com::sun::star::beans::XPropertySet;
100 using com::sun::star::container::XNameAccess;
103 #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
105 namespace pq_sdbc_driver
108 // struct ColumnMetaData
109 // {
110 // rtl::OUString tableName;
111 // rtl::OUString schemaTableName;
112 // rtl::OUString typeName;
113 // com::sun::star::sdbc::DataType type;
114 // sal_Int32 precision;
115 // sal_Int32 scale;
116 // sal_Bool isCurrency;
117 // sal_Bool isNullable;
118 // sal_Bool isAutoIncrement;
119 // sal_Bool isReadOnly;
120 // sal_Bool isSigned;
121 // };
123 // is not exported by the postgres header
124 const static int PQ_VARHDRSZ = sizeof( sal_Int32 );
126 static void extractPrecisionAndScale( sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
128 if( atttypmod < PQ_VARHDRSZ )
130 *precision = 0;
131 *scale = 0;
133 else
135 if( atttypmod & 0xffff0000 )
137 *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
138 *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
140 else
142 *precision = atttypmod - PQ_VARHDRSZ;
143 *scale = 0;
148 ResultSetMetaData::ResultSetMetaData(
149 const ::rtl::Reference< RefCountedMutex > & refMutex,
150 const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XResultSet > & origin,
151 ResultSet * pResultSet,
152 ConnectionSettings **ppSettings,
153 PGresult *pResult,
154 const rtl::OUString &schemaName,
155 const rtl::OUString &tableName ) :
156 m_refMutex( refMutex ),
157 m_origin( origin ),
158 m_ppSettings( ppSettings ),
159 m_colCount( PQnfields( pResult ) ),
160 m_tableName( tableName ),
161 m_schemaName( schemaName ),
162 m_checkedForTable( false ),
163 m_checkedForTypes( false ),
164 m_colDesc( PQnfields( pResult ) ),
165 m_pResultSet( pResultSet )
168 // extract all needed information from the result object, so that we don't
169 // need it anymore after this call !
170 for( int col = 0; col < m_colCount ; col ++ )
172 sal_Int32 size = PQfsize( pResult, col );
173 size = -1 == size ? 25 : size;
174 m_colDesc[col].displaySize = size;
176 extractPrecisionAndScale(
177 PQfmod( pResult, col ),
178 & ( m_colDesc[col].precision ),
179 & ( m_colDesc[col].scale ) );
180 char *name = PQfname( pResult, col );
181 m_colDesc[col].name = OUString( name, strlen(name) , (*m_ppSettings)->encoding );
182 m_colDesc[col].typeOid = PQftype( pResult, col );
183 m_colDesc[col].type = com::sun::star::sdbc::DataType::LONGVARCHAR;
187 // typedef std::hash_map<
188 // Oid,
189 // rtl::OUString,
190 // std::hash< Oid >,
191 // std::equal_to< Oid >,
192 // Allocator < std::pair< Oid, rtl::OUString > > > PqTypeMap;
195 void ResultSetMetaData::checkForTypes()
197 if( ! m_checkedForTypes )
199 Reference< XStatement > stmt =
200 extractConnectionFromStatement( m_origin->getStatement() )->createStatement();
201 DisposeGuard guard( stmt );
202 OUStringBuffer buf(128);
203 buf.appendAscii( "SELECT oid, typname, typtype FROM pg_type WHERE ");
204 for( int i = 0 ; i < m_colCount ; i ++ )
206 if( i > 0 )
207 buf.appendAscii( " OR " );
208 int oid = m_colDesc[i].typeOid;
209 buf.appendAscii( "oid=" );
210 buf.append( (sal_Int32) oid, 10 );
212 Reference< XResultSet > rs = stmt->executeQuery( buf.makeStringAndClear() );
213 Reference< XRow > xRow( rs, UNO_QUERY );
214 while( rs->next() )
216 sal_Int32 oid = xRow->getInt( 1 );
217 OUString typeName = xRow->getString( 2 );
218 OUString typType = xRow->getString( 3 );
220 sal_Int32 type = typeNameToDataType( typeName, typType );
222 for( int j = 0; j < m_colCount ; j ++ )
224 if( m_colDesc[j].typeOid == oid )
226 m_colDesc[j].typeName = typeName;
227 m_colDesc[j].type = type;
231 m_checkedForTypes = true;
235 void ResultSetMetaData::checkTable()
237 if( ! m_checkedForTable )
239 m_checkedForTable = true;
240 if( m_tableName.getLength() )
243 Reference< com::sun::star::container::XNameAccess > tables = (*m_ppSettings)->tables;
244 if( ! tables.is() )
247 Reference< XTablesSupplier > supplier =
248 Reference< XTablesSupplier > (
249 extractConnectionFromStatement( m_origin->getStatement() ), UNO_QUERY);
250 if( supplier.is() )
251 tables = supplier->getTables();
253 if( tables.is() )
255 OUString name = getTableName( 1 );
256 // if( tables->hasByName( name ) )
257 tables->getByName( name ) >>= m_table;
263 sal_Int32 ResultSetMetaData::getIntColumnProperty( const rtl::OUString & name, int index, int def )
265 sal_Int32 ret = def; // give defensive answers, when data is not available
268 MutexGuard guard( m_refMutex->mutex );
269 checkColumnIndex( index );
270 Reference< XPropertySet > set = getColumnByIndex( index );
272 if( set.is() )
274 set->getPropertyValue( name ) >>= ret;
277 catch( com::sun::star::uno::Exception & e )
280 return ret;
283 sal_Bool ResultSetMetaData::getBoolColumnProperty( const rtl::OUString & name, int index, sal_Bool def )
285 sal_Bool ret = def;
288 MutexGuard guard( m_refMutex->mutex );
289 checkColumnIndex( index );
290 Reference< XPropertySet > set = getColumnByIndex( index );
291 if( set.is() )
293 set->getPropertyValue( name ) >>= ret;
296 catch( com::sun::star::uno::Exception & e )
300 return ret;
303 Reference< com::sun::star::beans::XPropertySet > ResultSetMetaData::getColumnByIndex( int index )
305 Reference< XPropertySet > ret;
306 checkTable();
307 if( m_table.is() )
309 OUString columnName = getColumnName( index );
310 Reference< XColumnsSupplier > supplier( m_table, UNO_QUERY );
311 if( supplier.is() )
313 Reference< XNameAccess > columns = supplier->getColumns();
314 if( columns.is() && columns->hasByName( columnName ) )
316 columns->getByName( columnName ) >>= ret;
320 return ret;
323 // Methods
324 sal_Int32 ResultSetMetaData::getColumnCount( )
325 throw (SQLException, RuntimeException)
327 return m_colCount;
330 sal_Bool ResultSetMetaData::isAutoIncrement( sal_Int32 column )
331 throw (SQLException, RuntimeException)
334 sal_Bool ret = getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT, column, sal_False );
335 return ret;
338 sal_Bool ResultSetMetaData::isCaseSensitive( sal_Int32 column )
339 throw (SQLException, RuntimeException)
342 return sal_True; // ??? hmm, numeric types or
345 sal_Bool ResultSetMetaData::isSearchable( sal_Int32 column ) throw (SQLException, RuntimeException)
347 return sal_True; // mmm, what types are not searchable ?
350 sal_Bool ResultSetMetaData::isCurrency( sal_Int32 column ) throw (SQLException, RuntimeException)
352 return getBoolColumnProperty( getStatics().IS_CURRENCY, column, sal_False );
355 sal_Int32 ResultSetMetaData::isNullable( sal_Int32 column )
356 throw (SQLException, RuntimeException)
358 return getIntColumnProperty(
359 getStatics().IS_NULLABLE, column, com::sun::star::sdbc::ColumnValue::NULLABLE_UNKNOWN );
362 sal_Bool ResultSetMetaData::isSigned( sal_Int32 column )
363 throw (SQLException, RuntimeException)
365 return sal_True; //
368 sal_Int32 ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
369 throw (SQLException, RuntimeException)
371 MutexGuard guard( m_refMutex->mutex );
372 checkClosed();
373 checkColumnIndex( column );
374 return m_colDesc[column-1].displaySize;
377 ::rtl::OUString ResultSetMetaData::getColumnLabel( sal_Int32 column )
378 throw (SQLException, RuntimeException)
380 return getColumnName( column);
383 ::rtl::OUString ResultSetMetaData::getColumnName( sal_Int32 column ) throw (SQLException, RuntimeException)
385 MutexGuard guard( m_refMutex->mutex );
386 checkClosed();
387 checkColumnIndex( column );
389 return m_colDesc[column-1].name;
392 ::rtl::OUString ResultSetMetaData::getSchemaName( sal_Int32 column ) throw (SQLException, RuntimeException)
394 return m_schemaName;
399 sal_Int32 ResultSetMetaData::getPrecision( sal_Int32 column )
400 throw (SQLException, RuntimeException)
402 MutexGuard guard( m_refMutex->mutex );
403 checkClosed();
404 checkColumnIndex( column );
405 return m_colDesc[column-1].precision;
408 sal_Int32 ResultSetMetaData::getScale( sal_Int32 column )
409 throw (SQLException, RuntimeException)
411 MutexGuard guard( m_refMutex->mutex );
412 checkClosed();
413 checkColumnIndex( column );
414 return m_colDesc[column-1].scale;
417 ::rtl::OUString ResultSetMetaData::getTableName( sal_Int32 column )
418 throw (SQLException, RuntimeException)
420 rtl::OUString ret;
421 if( m_tableName.getLength() )
423 OUStringBuffer buf( 128 );
424 buf.append( m_schemaName );
425 buf.appendAscii( "." );
426 buf.append( m_tableName );
427 ret = buf.makeStringAndClear();
429 return ret;
432 ::rtl::OUString ResultSetMetaData::getCatalogName( sal_Int32 column )
433 throw (SQLException, RuntimeException)
435 // can do this through XConnection.getCatalog() !
436 return OUString();
438 sal_Int32 ResultSetMetaData::getColumnType( sal_Int32 column )
439 throw (SQLException, RuntimeException)
441 int ret = getIntColumnProperty( getStatics().TYPE, column, -100 );
442 if( -100 == ret )
444 checkForTypes();
445 if( com::sun::star::sdbc::DataType::LONGVARCHAR == m_colDesc[column-1].type && m_pResultSet )
446 m_colDesc[column-1].type = m_pResultSet->guessDataType( column );
447 ret = m_colDesc[column-1].type;
449 return ret;
452 ::rtl::OUString ResultSetMetaData::getColumnTypeName( sal_Int32 column )
453 throw (SQLException, RuntimeException)
455 ::rtl::OUString ret; // give defensive answers, when data is not available
458 MutexGuard guard( m_refMutex->mutex );
459 checkColumnIndex( column );
460 Reference< XPropertySet > set = getColumnByIndex( column );
462 if( set.is() )
464 set->getPropertyValue( getStatics().TYPE_NAME ) >>= ret;
466 else
468 checkForTypes();
469 ret = m_colDesc[column-1].typeName;
472 catch( com::sun::star::uno::Exception & e )
475 return ret;
479 sal_Bool ResultSetMetaData::isReadOnly( sal_Int32 column )
480 throw (SQLException, RuntimeException)
482 return sal_False;
485 sal_Bool ResultSetMetaData::isWritable( sal_Int32 column )
486 throw (SQLException, RuntimeException)
488 return ! isReadOnly( column ); // what's the sense if this method ?
491 sal_Bool ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
492 throw (SQLException, RuntimeException)
494 return isWritable(column); // uhh, now it becomes really esoteric ....
496 ::rtl::OUString ResultSetMetaData::getColumnServiceName( sal_Int32 column )
497 throw (SQLException, RuntimeException)
499 return OUString();
502 void ResultSetMetaData::checkClosed()
503 throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
505 // we never close
508 void ResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
509 throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
511 if( columnIndex < 1 || columnIndex > m_colCount )
513 OUStringBuffer buf(128);
515 buf.appendAscii( "pq_resultsetmetadata: index out of range (expected 1 to " );
516 buf.append( m_colCount );
517 buf.appendAscii( ", got " );
518 buf.append( columnIndex );
519 throw SQLException(
520 buf.makeStringAndClear(), *this, OUString(), 1, Any() );