Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / postgresql / pq_resultsetmetadata.cxx
blob1e57850187d030a6cbb79d1024621c1cdb52dff7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * Effective License of whole file:
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.
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.
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
20 * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
22 * The Contents of this file are made available subject to the terms of
23 * the GNU Lesser General Public License Version 2.1
25 * Copyright: 2000 by Sun Microsystems, Inc.
27 * Contributor(s): Joerg Budischewski
29 * All parts contributed on or after August 2011:
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/.
35 ************************************************************************/
37 #include <rtl/ustrbuf.hxx>
39 #include "pq_resultsetmetadata.hxx"
40 #include "pq_resultset.hxx"
41 #include "pq_tools.hxx"
42 #include "pq_statics.hxx"
44 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
45 #include <com/sun/star/sdbc/ColumnValue.hpp>
46 #include <com/sun/star/sdbc/XRow.hpp>
48 #include <string.h>
50 using osl::Mutex;
51 using osl::MutexGuard;
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;
61 using com::sun::star::lang::IllegalArgumentException;
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;
70 using com::sun::star::beans::XPropertySet;
71 using com::sun::star::container::XNameAccess;
74 namespace pq_sdbc_driver
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 // };
92 // is not exported by the postgres header
93 const static int PQ_VARHDRSZ = sizeof( sal_Int32 );
95 static void extractPrecisionAndScale( sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
97 if( atttypmod < PQ_VARHDRSZ )
99 *precision = 0;
100 *scale = 0;
102 else
104 if( atttypmod & 0xffff0000 )
106 *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
107 *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
109 else
111 *precision = atttypmod - PQ_VARHDRSZ;
112 *scale = 0;
117 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 m_colDesc( PQnfields( pResult ) ),
131 m_pResultSet( pResultSet ),
132 m_checkedForTable( false ),
133 m_checkedForTypes( false ),
134 m_colCount( PQnfields( pResult ) )
137 // extract all needed information from the result object, so that we don't
138 // need it anymore after this call !
139 for( int col = 0; col < m_colCount ; col ++ )
141 sal_Int32 size = PQfsize( pResult, col );
142 size = -1 == size ? 25 : size;
143 m_colDesc[col].displaySize = size;
145 extractPrecisionAndScale(
146 PQfmod( pResult, col ),
147 & ( m_colDesc[col].precision ),
148 & ( m_colDesc[col].scale ) );
149 char *name = PQfname( pResult, col );
150 m_colDesc[col].name = OUString( name, strlen(name) , (*m_ppSettings)->encoding );
151 m_colDesc[col].typeOid = PQftype( pResult, col );
152 m_colDesc[col].type = com::sun::star::sdbc::DataType::LONGVARCHAR;
156 void ResultSetMetaData::checkForTypes()
158 if( ! m_checkedForTypes )
160 Reference< XStatement > stmt =
161 extractConnectionFromStatement( m_origin->getStatement() )->createStatement();
162 DisposeGuard guard( stmt );
163 OUStringBuffer buf(128);
164 buf.appendAscii( "SELECT oid, typname, typtype FROM pg_type WHERE ");
165 for( int i = 0 ; i < m_colCount ; i ++ )
167 if( i > 0 )
168 buf.appendAscii( " OR " );
169 int oid = m_colDesc[i].typeOid;
170 buf.appendAscii( "oid=" );
171 buf.append( (sal_Int32) oid, 10 );
173 Reference< XResultSet > rs = stmt->executeQuery( buf.makeStringAndClear() );
174 Reference< XRow > xRow( rs, UNO_QUERY );
175 while( rs->next() )
177 Oid oid = xRow->getInt( 1 );
178 OUString typeName = xRow->getString( 2 );
179 OUString typType = xRow->getString( 3 );
181 sal_Int32 type = typeNameToDataType( typeName, typType );
183 for( sal_Int32 j = 0; j < m_colCount ; j ++ )
185 if( m_colDesc[j].typeOid == oid )
187 m_colDesc[j].typeName = typeName;
188 m_colDesc[j].type = type;
192 m_checkedForTypes = true;
196 void ResultSetMetaData::checkTable()
198 if( ! m_checkedForTable )
200 m_checkedForTable = true;
201 if( m_tableName.getLength() )
204 Reference< com::sun::star::container::XNameAccess > tables = (*m_ppSettings)->tables;
205 if( ! tables.is() )
208 Reference< XTablesSupplier > supplier =
209 Reference< XTablesSupplier > (
210 extractConnectionFromStatement( m_origin->getStatement() ), UNO_QUERY);
211 if( supplier.is() )
212 tables = supplier->getTables();
214 if( tables.is() )
216 const OUString name (getTableName ( 1 ));
217 const OUString schema (getSchemaName( 1 ));
218 const OUString composedName( schema.isEmpty() ? name : (schema + "." + name) );
219 tables->getByName( composedName ) >>= m_table;
225 sal_Int32 ResultSetMetaData::getIntColumnProperty( const OUString & name, int index, int def )
227 sal_Int32 ret = def; // give defensive answers, when data is not available
230 MutexGuard guard( m_refMutex->mutex );
231 checkColumnIndex( index );
232 Reference< XPropertySet > set = getColumnByIndex( index );
234 if( set.is() )
236 set->getPropertyValue( name ) >>= ret;
239 catch( com::sun::star::uno::Exception & )
242 return ret;
245 bool ResultSetMetaData::getBoolColumnProperty( const OUString & name, int index, bool def )
247 bool ret = def;
250 MutexGuard guard( m_refMutex->mutex );
251 checkColumnIndex( index );
252 Reference< XPropertySet > set = getColumnByIndex( index );
253 if( set.is() )
255 set->getPropertyValue( name ) >>= ret;
258 catch( com::sun::star::uno::Exception & )
262 return ret;
265 Reference< com::sun::star::beans::XPropertySet > ResultSetMetaData::getColumnByIndex( int index )
267 Reference< XPropertySet > ret;
268 checkTable();
269 if( m_table.is() )
271 OUString columnName = getColumnName( index );
272 Reference< XColumnsSupplier > supplier( m_table, UNO_QUERY );
273 if( supplier.is() )
275 Reference< XNameAccess > columns = supplier->getColumns();
276 if( columns.is() && columns->hasByName( columnName ) )
278 columns->getByName( columnName ) >>= ret;
282 return ret;
285 // Methods
286 sal_Int32 ResultSetMetaData::getColumnCount( )
287 throw (SQLException, RuntimeException, std::exception)
289 return m_colCount;
292 sal_Bool ResultSetMetaData::isAutoIncrement( sal_Int32 column )
293 throw (SQLException, RuntimeException, std::exception)
296 bool ret = getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT, column, false );
297 return ret;
300 sal_Bool ResultSetMetaData::isCaseSensitive( sal_Int32 column )
301 throw (SQLException, RuntimeException, std::exception)
303 (void) column;
304 return sal_True; // ??? hmm, numeric types or
307 sal_Bool ResultSetMetaData::isSearchable( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
309 (void) column;
310 return sal_True; // mmm, what types are not searchable ?
313 sal_Bool ResultSetMetaData::isCurrency( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
315 return getBoolColumnProperty( getStatics().IS_CURRENCY, column, false );
318 sal_Int32 ResultSetMetaData::isNullable( sal_Int32 column )
319 throw (SQLException, RuntimeException, std::exception)
321 return getIntColumnProperty(
322 getStatics().IS_NULLABLE, column, com::sun::star::sdbc::ColumnValue::NULLABLE_UNKNOWN );
325 sal_Bool ResultSetMetaData::isSigned( sal_Int32 column )
326 throw (SQLException, RuntimeException, std::exception)
328 (void) column;
329 return sal_True;
332 sal_Int32 ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
333 throw (SQLException, RuntimeException, std::exception)
335 MutexGuard guard( m_refMutex->mutex );
336 checkClosed();
337 checkColumnIndex( column );
338 return m_colDesc[column-1].displaySize;
341 OUString ResultSetMetaData::getColumnLabel( sal_Int32 column )
342 throw (SQLException, RuntimeException, std::exception)
344 return getColumnName( column);
347 OUString ResultSetMetaData::getColumnName( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
349 MutexGuard guard( m_refMutex->mutex );
350 checkClosed();
351 checkColumnIndex( column );
353 return m_colDesc[column-1].name;
356 OUString ResultSetMetaData::getSchemaName( sal_Int32 column ) throw (SQLException, RuntimeException, std::exception)
358 (void) column;
359 return m_schemaName;
362 sal_Int32 ResultSetMetaData::getPrecision( sal_Int32 column )
363 throw (SQLException, RuntimeException, std::exception)
365 MutexGuard guard( m_refMutex->mutex );
366 checkClosed();
367 checkColumnIndex( column );
368 return m_colDesc[column-1].precision;
371 sal_Int32 ResultSetMetaData::getScale( sal_Int32 column )
372 throw (SQLException, RuntimeException, std::exception)
374 MutexGuard guard( m_refMutex->mutex );
375 checkClosed();
376 checkColumnIndex( column );
377 return m_colDesc[column-1].scale;
380 OUString ResultSetMetaData::getTableName( sal_Int32 column )
381 throw (SQLException, RuntimeException, std::exception)
383 (void) column;
384 // LEM TODO This is very fishy.. Should probably return the table to which that column belongs!
385 return m_tableName;
388 OUString ResultSetMetaData::getCatalogName( sal_Int32 column )
389 throw (SQLException, RuntimeException, std::exception)
391 (void) column;
392 // can do this through XConnection.getCatalog() !
393 return OUString();
395 sal_Int32 ResultSetMetaData::getColumnType( sal_Int32 column )
396 throw (SQLException, RuntimeException, std::exception)
398 int ret = getIntColumnProperty( getStatics().TYPE, column, -100 );
399 if( -100 == ret )
401 checkForTypes();
402 if( com::sun::star::sdbc::DataType::LONGVARCHAR == m_colDesc[column-1].type && m_pResultSet )
403 m_colDesc[column-1].type = m_pResultSet->guessDataType( column );
404 ret = m_colDesc[column-1].type;
406 return ret;
409 OUString ResultSetMetaData::getColumnTypeName( sal_Int32 column )
410 throw (SQLException, RuntimeException, std::exception)
412 OUString ret; // give defensive answers, when data is not available
415 MutexGuard guard( m_refMutex->mutex );
416 checkColumnIndex( column );
417 Reference< XPropertySet > set = getColumnByIndex( column );
419 if( set.is() )
421 set->getPropertyValue( getStatics().TYPE_NAME ) >>= ret;
423 else
425 checkForTypes();
426 ret = m_colDesc[column-1].typeName;
429 catch( com::sun::star::uno::Exception & )
432 return ret;
436 sal_Bool ResultSetMetaData::isReadOnly( sal_Int32 column )
437 throw (SQLException, RuntimeException, std::exception)
439 (void) column;
440 return sal_False;
443 sal_Bool ResultSetMetaData::isWritable( sal_Int32 column )
444 throw (SQLException, RuntimeException, std::exception)
446 return ! isReadOnly( column ); // what's the sense if this method ?
449 sal_Bool ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
450 throw (SQLException, RuntimeException, std::exception)
452 return isWritable(column); // uhh, now it becomes really esoteric ....
454 OUString ResultSetMetaData::getColumnServiceName( sal_Int32 column )
455 throw (SQLException, RuntimeException, std::exception)
457 (void) column;
458 return OUString();
461 void ResultSetMetaData::checkClosed()
462 throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
464 // we never close
467 void ResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
468 throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
470 if( columnIndex < 1 || columnIndex > m_colCount )
472 OUStringBuffer buf(128);
474 buf.appendAscii( "pq_resultsetmetadata: index out of range (expected 1 to " );
475 buf.append( m_colCount );
476 buf.appendAscii( ", got " );
477 buf.append( columnIndex );
478 throw SQLException(
479 buf.makeStringAndClear(), *this, OUString(), 1, Any() );
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */