1 /*************************************************************************
3 * $RCSfile: pq_resultsetmetadata.cxx,v $
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,
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>
75 using osl::MutexGuard
;
78 using rtl::OUStringBuffer
;
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
110 // rtl::OUString tableName;
111 // rtl::OUString schemaTableName;
112 // rtl::OUString typeName;
113 // com::sun::star::sdbc::DataType type;
114 // sal_Int32 precision;
116 // sal_Bool isCurrency;
117 // sal_Bool isNullable;
118 // sal_Bool isAutoIncrement;
119 // sal_Bool isReadOnly;
120 // sal_Bool isSigned;
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
)
135 if( atttypmod
& 0xffff0000 )
137 *precision
= ( ( atttypmod
- PQ_VARHDRSZ
) >> 16 ) & 0xffff;
138 *scale
= (atttypmod
- PQ_VARHDRSZ
) & 0xffff;
142 *precision
= atttypmod
- PQ_VARHDRSZ
;
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
,
154 const rtl::OUString
&schemaName
,
155 const rtl::OUString
&tableName
) :
156 m_refMutex( refMutex
),
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<
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
++ )
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
);
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
;
247 Reference
< XTablesSupplier
> supplier
=
248 Reference
< XTablesSupplier
> (
249 extractConnectionFromStatement( m_origin
->getStatement() ), UNO_QUERY
);
251 tables
= supplier
->getTables();
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
);
274 set
->getPropertyValue( name
) >>= ret
;
277 catch( com::sun::star::uno::Exception
& e
)
283 sal_Bool
ResultSetMetaData::getBoolColumnProperty( const rtl::OUString
& name
, int index
, sal_Bool def
)
288 MutexGuard
guard( m_refMutex
->mutex
);
289 checkColumnIndex( index
);
290 Reference
< XPropertySet
> set
= getColumnByIndex( index
);
293 set
->getPropertyValue( name
) >>= ret
;
296 catch( com::sun::star::uno::Exception
& e
)
303 Reference
< com::sun::star::beans::XPropertySet
> ResultSetMetaData::getColumnByIndex( int index
)
305 Reference
< XPropertySet
> ret
;
309 OUString columnName
= getColumnName( index
);
310 Reference
< XColumnsSupplier
> supplier( m_table
, UNO_QUERY
);
313 Reference
< XNameAccess
> columns
= supplier
->getColumns();
314 if( columns
.is() && columns
->hasByName( columnName
) )
316 columns
->getByName( columnName
) >>= ret
;
324 sal_Int32
ResultSetMetaData::getColumnCount( )
325 throw (SQLException
, RuntimeException
)
330 sal_Bool
ResultSetMetaData::isAutoIncrement( sal_Int32 column
)
331 throw (SQLException
, RuntimeException
)
334 sal_Bool ret
= getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT
, column
, sal_False
);
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
)
368 sal_Int32
ResultSetMetaData::getColumnDisplaySize( sal_Int32 column
)
369 throw (SQLException
, RuntimeException
)
371 MutexGuard
guard( m_refMutex
->mutex
);
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
);
387 checkColumnIndex( column
);
389 return m_colDesc
[column
-1].name
;
392 ::rtl::OUString
ResultSetMetaData::getSchemaName( sal_Int32 column
) throw (SQLException
, RuntimeException
)
399 sal_Int32
ResultSetMetaData::getPrecision( sal_Int32 column
)
400 throw (SQLException
, RuntimeException
)
402 MutexGuard
guard( m_refMutex
->mutex
);
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
);
413 checkColumnIndex( column
);
414 return m_colDesc
[column
-1].scale
;
417 ::rtl::OUString
ResultSetMetaData::getTableName( sal_Int32 column
)
418 throw (SQLException
, RuntimeException
)
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();
432 ::rtl::OUString
ResultSetMetaData::getCatalogName( sal_Int32 column
)
433 throw (SQLException
, RuntimeException
)
435 // can do this through XConnection.getCatalog() !
438 sal_Int32
ResultSetMetaData::getColumnType( sal_Int32 column
)
439 throw (SQLException
, RuntimeException
)
441 int ret
= getIntColumnProperty( getStatics().TYPE
, column
, -100 );
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
;
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
);
464 set
->getPropertyValue( getStatics().TYPE_NAME
) >>= ret
;
469 ret
= m_colDesc
[column
-1].typeName
;
472 catch( com::sun::star::uno::Exception
& e
)
479 sal_Bool
ResultSetMetaData::isReadOnly( sal_Int32 column
)
480 throw (SQLException
, RuntimeException
)
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
)
502 void ResultSetMetaData::checkClosed()
503 throw (::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
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
);
520 buf
.makeStringAndClear(), *this, OUString(), 1, Any() );