Use correct object
[LibreOffice.git] / connectivity / source / drivers / postgresql / pq_resultsetmetadata.cxx
blob26b11de27985a4200bb422e1df9134a89433f9ca
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/DataType.hpp>
47 #include <com/sun/star/sdbc/SQLException.hpp>
48 #include <com/sun/star/sdbc/XRow.hpp>
49 #include <utility>
51 #include <string.h>
53 using osl::MutexGuard;
56 using com::sun::star::uno::Any;
57 using com::sun::star::uno::Exception;
58 using com::sun::star::uno::Reference;
59 using com::sun::star::uno::UNO_QUERY;
62 using com::sun::star::sdbc::SQLException;
63 using com::sun::star::sdbc::XStatement;
64 using com::sun::star::sdbc::XRow;
65 using com::sun::star::sdbc::XResultSet;
66 using com::sun::star::sdbcx::XColumnsSupplier;
67 using com::sun::star::sdbcx::XTablesSupplier;
69 using com::sun::star::beans::XPropertySet;
70 using com::sun::star::container::XNameAccess;
73 namespace pq_sdbc_driver
76 // struct ColumnMetaData
77 // {
78 // OUString tableName;
79 // OUString schemaTableName;
80 // OUString typeName;
81 // css::sdbc::DataType type;
82 // sal_Int32 precision;
83 // sal_Int32 scale;
84 // sal_Bool isCurrency;
85 // sal_Bool isNullable;
86 // sal_Bool isAutoIncrement;
87 // sal_Bool isReadOnly;
88 // sal_Bool isSigned;
89 // };
91 // is not exported by the postgres header
92 const int PQ_VARHDRSZ = sizeof( sal_Int32 );
94 static void extractPrecisionAndScale( sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
96 if( atttypmod < PQ_VARHDRSZ )
98 *precision = 0;
99 *scale = 0;
101 else
103 if( atttypmod & 0xffff0000 )
105 *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
106 *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
108 else
110 *precision = atttypmod - PQ_VARHDRSZ;
111 *scale = 0;
116 ResultSetMetaData::ResultSetMetaData(
117 ::rtl::Reference< comphelper::RefCountedMutex > refMutex,
118 css::uno::Reference< css::sdbc::XResultSet > origin,
119 ResultSet * pResultSet,
120 ConnectionSettings **ppSettings,
121 PGresult const *pResult,
122 OUString schemaName,
123 OUString tableName ) :
124 m_xMutex(std::move( refMutex )),
125 m_ppSettings( ppSettings ),
126 m_origin(std::move( origin )),
127 m_tableName(std::move( tableName )),
128 m_schemaName(std::move( schemaName )),
129 m_colDesc( PQnfields( pResult ) ),
130 m_pResultSet( pResultSet ),
131 m_checkedForTable( false ),
132 m_checkedForTypes( false ),
133 m_colCount( PQnfields( pResult ) )
136 // extract all needed information from the result object, so that we don't
137 // need it anymore after this call !
138 for( int col = 0; col < m_colCount ; col ++ )
140 sal_Int32 size = PQfsize( pResult, col );
141 size = -1 == size ? 25 : size;
142 m_colDesc[col].displaySize = size;
144 extractPrecisionAndScale(
145 PQfmod( pResult, col ),
146 & ( m_colDesc[col].precision ),
147 & ( m_colDesc[col].scale ) );
148 char *name = PQfname( pResult, col );
149 m_colDesc[col].name = OUString( name, strlen(name) , ConnectionSettings::encoding );
150 m_colDesc[col].typeOid = PQftype( pResult, col );
151 m_colDesc[col].type = css::sdbc::DataType::LONGVARCHAR;
155 void ResultSetMetaData::checkForTypes()
157 if( m_checkedForTypes )
158 return;
160 Reference< XStatement > stmt =
161 extractConnectionFromStatement( m_origin->getStatement() )->createStatement();
162 DisposeGuard guard( stmt );
163 OUStringBuffer buf(128);
164 buf.append( "SELECT oid, typname, typtype FROM pg_type WHERE ");
165 for( int i = 0 ; i < m_colCount ; i ++ )
167 if( i > 0 )
168 buf.append( " OR " );
169 int oid = m_colDesc[i].typeOid;
170 buf.append( "oid=" + OUString::number(static_cast<sal_Int32>(oid)) );
172 Reference< XResultSet > rs = stmt->executeQuery( buf.makeStringAndClear() );
173 Reference< XRow > xRow( rs, UNO_QUERY );
174 while( rs->next() )
176 Oid oid = xRow->getInt( 1 );
177 OUString typeName = xRow->getString( 2 );
178 OUString typType = xRow->getString( 3 );
180 sal_Int32 type = typeNameToDataType( typeName, typType );
182 for( sal_Int32 j = 0; j < m_colCount ; j ++ )
184 if( m_colDesc[j].typeOid == oid )
186 m_colDesc[j].typeName = typeName;
187 m_colDesc[j].type = type;
191 m_checkedForTypes = true;
194 void ResultSetMetaData::checkTable()
196 if( m_checkedForTable )
197 return;
199 m_checkedForTable = true;
200 if( !m_tableName.getLength() )
201 return;
203 Reference< css::container::XNameAccess > tables = (*m_ppSettings)->tables;
204 if( ! tables.is() )
207 Reference< XTablesSupplier > supplier(
208 extractConnectionFromStatement( m_origin->getStatement() ), UNO_QUERY);
209 if( supplier.is() )
210 tables = supplier->getTables();
212 if( tables.is() )
214 const OUString name (getTableName ( 1 ));
215 const OUString schema (getSchemaName( 1 ));
216 const OUString composedName( schema.isEmpty() ? name : (schema + "." + name) );
217 tables->getByName( composedName ) >>= m_table;
221 sal_Int32 ResultSetMetaData::getIntColumnProperty( const OUString & name, int index, int def )
223 sal_Int32 ret = def; // give defensive answers, when data is not available
226 MutexGuard guard( m_xMutex->GetMutex() );
227 checkColumnIndex( index );
228 Reference< XPropertySet > set = getColumnByIndex( index );
230 if( set.is() )
232 set->getPropertyValue( name ) >>= ret;
235 catch( css::uno::Exception & )
238 return ret;
241 bool ResultSetMetaData::getBoolColumnProperty( const OUString & name, int index, bool def )
243 bool ret = def;
246 MutexGuard guard( m_xMutex->GetMutex() );
247 checkColumnIndex( index );
248 Reference< XPropertySet > set = getColumnByIndex( index );
249 if( set.is() )
251 set->getPropertyValue( name ) >>= ret;
254 catch( css::uno::Exception & )
258 return ret;
261 Reference< css::beans::XPropertySet > ResultSetMetaData::getColumnByIndex( int index )
263 Reference< XPropertySet > ret;
264 checkTable();
265 if( m_table.is() )
267 OUString columnName = getColumnName( index );
268 Reference< XColumnsSupplier > supplier( m_table, UNO_QUERY );
269 if( supplier.is() )
271 Reference< XNameAccess > columns = supplier->getColumns();
272 if( columns.is() && columns->hasByName( columnName ) )
274 columns->getByName( columnName ) >>= ret;
278 return ret;
281 // Methods
282 sal_Int32 ResultSetMetaData::getColumnCount( )
284 return m_colCount;
287 sal_Bool ResultSetMetaData::isAutoIncrement( sal_Int32 column )
290 bool ret = getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT, column, false );
291 return ret;
294 sal_Bool ResultSetMetaData::isCaseSensitive( sal_Int32 )
296 return true; // ??? hmm, numeric types or
299 sal_Bool ResultSetMetaData::isSearchable( sal_Int32 )
301 return true; // mmm, what types are not searchable ?
304 sal_Bool ResultSetMetaData::isCurrency( sal_Int32 column )
306 return getBoolColumnProperty( getStatics().IS_CURRENCY, column, false );
309 sal_Int32 ResultSetMetaData::isNullable( sal_Int32 column )
311 return getIntColumnProperty(
312 getStatics().IS_NULLABLE, column, css::sdbc::ColumnValue::NULLABLE_UNKNOWN );
315 sal_Bool ResultSetMetaData::isSigned( sal_Int32 )
317 return true;
320 sal_Int32 ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
322 MutexGuard guard( m_xMutex->GetMutex() );
323 checkColumnIndex( column );
324 return m_colDesc[column-1].displaySize;
327 OUString ResultSetMetaData::getColumnLabel( sal_Int32 column )
329 return getColumnName( column);
332 OUString ResultSetMetaData::getColumnName( sal_Int32 column )
334 MutexGuard guard( m_xMutex->GetMutex() );
335 checkColumnIndex( column );
337 return m_colDesc[column-1].name;
340 OUString ResultSetMetaData::getSchemaName( sal_Int32 )
342 return m_schemaName;
345 sal_Int32 ResultSetMetaData::getPrecision( sal_Int32 column )
347 MutexGuard guard( m_xMutex->GetMutex() );
348 checkColumnIndex( column );
349 return m_colDesc[column-1].precision;
352 sal_Int32 ResultSetMetaData::getScale( sal_Int32 column )
354 MutexGuard guard( m_xMutex->GetMutex() );
355 checkColumnIndex( column );
356 return m_colDesc[column-1].scale;
359 OUString ResultSetMetaData::getTableName( sal_Int32 )
361 // LEM TODO This is very fishy... Should probably return the table to which that column belongs!
362 return m_tableName;
365 OUString ResultSetMetaData::getCatalogName( sal_Int32 )
367 // can do this through XConnection.getCatalog() !
368 return OUString();
370 sal_Int32 ResultSetMetaData::getColumnType( sal_Int32 column )
372 int ret = getIntColumnProperty( getStatics().TYPE, column, -100 );
373 if( -100 == ret )
375 checkForTypes();
376 if( css::sdbc::DataType::LONGVARCHAR == m_colDesc[column-1].type && m_pResultSet )
377 m_colDesc[column-1].type = m_pResultSet->guessDataType( column );
378 ret = m_colDesc[column-1].type;
380 return ret;
383 OUString ResultSetMetaData::getColumnTypeName( sal_Int32 column )
385 OUString ret; // give defensive answers, when data is not available
388 MutexGuard guard( m_xMutex->GetMutex() );
389 checkColumnIndex( column );
390 Reference< XPropertySet > set = getColumnByIndex( column );
392 if( set.is() )
394 set->getPropertyValue( getStatics().TYPE_NAME ) >>= ret;
396 else
398 checkForTypes();
399 ret = m_colDesc[column-1].typeName;
402 catch( css::uno::Exception & )
405 return ret;
409 sal_Bool ResultSetMetaData::isReadOnly( sal_Int32 )
411 return false;
414 sal_Bool ResultSetMetaData::isWritable( sal_Int32 column )
416 return ! isReadOnly( column ); // what's the sense if this method ?
419 sal_Bool ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
421 return isWritable(column); // uhh, now it becomes really esoteric...
423 OUString ResultSetMetaData::getColumnServiceName( sal_Int32 )
425 return OUString();
428 void ResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
430 if( columnIndex < 1 || columnIndex > m_colCount )
432 throw SQLException(
433 "pq_resultsetmetadata: index out of range (expected 1 to "
434 + OUString::number( m_colCount ) + ", got " + OUString::number( columnIndex ),
435 *this, OUString(), 1, Any() );
441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */