summaryrefslogtreecommitdiffstats
path: root/connectivity/source/drivers/postgresql
diff options
context:
space:
mode:
Diffstat (limited to 'connectivity/source/drivers/postgresql')
-rw-r--r--connectivity/source/drivers/postgresql/postgresql-sdbc-impl.component17
-rw-r--r--connectivity/source/drivers/postgresql/postgresql-sdbc.component17
-rw-r--r--connectivity/source/drivers/postgresql/pq_array.cxx122
-rw-r--r--connectivity/source/drivers/postgresql/pq_array.hxx97
-rw-r--r--connectivity/source/drivers/postgresql/pq_baseresultset.cxx613
-rw-r--r--connectivity/source/drivers/postgresql/pq_baseresultset.hxx203
-rw-r--r--connectivity/source/drivers/postgresql/pq_connection.cxx571
-rw-r--r--connectivity/source/drivers/postgresql/pq_connection.hxx194
-rw-r--r--connectivity/source/drivers/postgresql/pq_databasemetadata.cxx2511
-rw-r--r--connectivity/source/drivers/postgresql/pq_databasemetadata.hxx237
-rw-r--r--connectivity/source/drivers/postgresql/pq_driver.cxx148
-rw-r--r--connectivity/source/drivers/postgresql/pq_driver.hxx116
-rw-r--r--connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.cxx214
-rw-r--r--connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.hxx106
-rw-r--r--connectivity/source/drivers/postgresql/pq_preparedstatement.cxx738
-rw-r--r--connectivity/source/drivers/postgresql/pq_preparedstatement.hxx221
-rw-r--r--connectivity/source/drivers/postgresql/pq_resultset.cxx308
-rw-r--r--connectivity/source/drivers/postgresql/pq_resultset.hxx94
-rw-r--r--connectivity/source/drivers/postgresql/pq_resultsetmetadata.cxx441
-rw-r--r--connectivity/source/drivers/postgresql/pq_resultsetmetadata.hxx127
-rw-r--r--connectivity/source/drivers/postgresql/pq_sequenceresultset.cxx125
-rw-r--r--connectivity/source/drivers/postgresql/pq_sequenceresultset.hxx92
-rw-r--r--connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.cxx191
-rw-r--r--connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.hxx89
-rw-r--r--connectivity/source/drivers/postgresql/pq_statement.cxx888
-rw-r--r--connectivity/source/drivers/postgresql/pq_statement.hxx198
-rw-r--r--connectivity/source/drivers/postgresql/pq_statics.cxx626
-rw-r--r--connectivity/source/drivers/postgresql/pq_statics.hxx239
-rw-r--r--connectivity/source/drivers/postgresql/pq_tools.cxx1249
-rw-r--r--connectivity/source/drivers/postgresql/pq_tools.hxx176
-rw-r--r--connectivity/source/drivers/postgresql/pq_updateableresultset.cxx550
-rw-r--r--connectivity/source/drivers/postgresql/pq_updateableresultset.hxx169
-rw-r--r--connectivity/source/drivers/postgresql/pq_xbase.cxx215
-rw-r--r--connectivity/source/drivers/postgresql/pq_xbase.hxx131
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcolumn.cxx95
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcolumn.hxx82
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcolumns.cxx560
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcolumns.hxx122
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcontainer.cxx409
-rw-r--r--connectivity/source/drivers/postgresql/pq_xcontainer.hxx188
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindex.cxx186
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindex.hxx123
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexcolumn.cxx96
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexcolumn.hxx83
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexcolumns.cxx267
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexcolumns.hxx110
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexes.cxx302
-rw-r--r--connectivity/source/drivers/postgresql/pq_xindexes.hxx102
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkey.cxx182
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkey.hxx119
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeycolumn.cxx95
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeycolumn.hxx82
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeycolumns.cxx238
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeycolumns.hxx101
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeys.cxx294
-rw-r--r--connectivity/source/drivers/postgresql/pq_xkeys.hxx101
-rw-r--r--connectivity/source/drivers/postgresql/pq_xtable.cxx394
-rw-r--r--connectivity/source/drivers/postgresql/pq_xtable.hxx161
-rw-r--r--connectivity/source/drivers/postgresql/pq_xtables.cxx369
-rw-r--r--connectivity/source/drivers/postgresql/pq_xtables.hxx91
-rw-r--r--connectivity/source/drivers/postgresql/pq_xuser.cxx172
-rw-r--r--connectivity/source/drivers/postgresql/pq_xuser.hxx93
-rw-r--r--connectivity/source/drivers/postgresql/pq_xusers.cxx202
-rw-r--r--connectivity/source/drivers/postgresql/pq_xusers.hxx82
-rw-r--r--connectivity/source/drivers/postgresql/pq_xview.cxx218
-rw-r--r--connectivity/source/drivers/postgresql/pq_xview.hxx92
-rw-r--r--connectivity/source/drivers/postgresql/pq_xviews.cxx219
-rw-r--r--connectivity/source/drivers/postgresql/pq_xviews.hxx88
68 files changed, 18151 insertions, 0 deletions
diff --git a/connectivity/source/drivers/postgresql/postgresql-sdbc-impl.component b/connectivity/source/drivers/postgresql/postgresql-sdbc-impl.component
new file mode 100644
index 000000000..8c5a6ff05
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/postgresql-sdbc-impl.component
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="org.openoffice.comp.connectivity.pq.Connection.noext"
+ constructor="connectivity_postgresql_Connection_get_implementation">
+ <service name="com.sun.star.sdbc.Connection"/>
+ </implementation>
+</component>
diff --git a/connectivity/source/drivers/postgresql/postgresql-sdbc.component b/connectivity/source/drivers/postgresql/postgresql-sdbc.component
new file mode 100644
index 000000000..a14ab2c96
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/postgresql-sdbc.component
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="org.openoffice.comp.connectivity.pq.Driver.noext"
+ constructor="connectivity_pq_sdbc_driver_get_implementation" single-instance="true">
+ <service name="com.sun.star.sdbc.Driver"/>
+ </implementation>
+</component>
diff --git a/connectivity/source/drivers/postgresql/pq_array.cxx b/connectivity/source/drivers/postgresql/pq_array.cxx
new file mode 100644
index 000000000..841ed70c6
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_array.cxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <comphelper/sequence.hxx>
+
+
+#include "pq_array.hxx"
+#include "pq_statics.hxx"
+#include "pq_sequenceresultset.hxx"
+
+
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::uno::Any;
+
+using com::sun::star::uno::Sequence;
+namespace pq_sdbc_driver
+{
+
+
+OUString Array::getBaseTypeName( )
+{
+ return "varchar";
+}
+
+sal_Int32 Array::getBaseType( )
+{
+ return css::sdbc::DataType::VARCHAR;
+}
+
+css::uno::Sequence< css::uno::Any > Array::getArray(
+ const css::uno::Reference< css::container::XNameAccess >& /* typeMap */ )
+{
+ return comphelper::containerToSequence(m_data);
+}
+
+css::uno::Sequence< css::uno::Any > Array::getArrayAtIndex(
+ sal_Int32 index,
+ sal_Int32 count,
+ const css::uno::Reference< css::container::XNameAccess >& /* typeMap */ )
+{
+ checkRange( index, count );
+ return Sequence< Any > ( &m_data[index-1], count );
+}
+
+css::uno::Reference< css::sdbc::XResultSet > Array::getResultSet(
+ const css::uno::Reference< css::container::XNameAccess >& typeMap )
+{
+ return getResultSetAtIndex( 0 , m_data.size() , typeMap );
+}
+
+css::uno::Reference< css::sdbc::XResultSet > Array::getResultSetAtIndex(
+ sal_Int32 index,
+ sal_Int32 count,
+ const css::uno::Reference< css::container::XNameAccess >& /* typeMap */ )
+{
+ checkRange( index, count );
+ std::vector< std::vector< Any > > ret( count );
+
+ for( int i = 0 ; i < count ; i ++ )
+ {
+ std::vector< Any > row( 2 );
+ row[0] <<= static_cast<sal_Int32>( i + index );
+ row[1] = m_data[i+index-1];
+ ret[i] = row;
+ }
+
+ return new SequenceResultSet(
+ m_xMutex, m_owner, std::vector(getStatics().resultSetArrayColumnNames), std::move(ret), m_tc );
+}
+
+
+void Array::checkRange( sal_Int32 index, sal_Int32 count )
+{
+ if( index >= 1 && index -1 + count <= static_cast<sal_Int32>(m_data.size()) )
+ return;
+ throw SQLException(
+ "Array::getArrayAtIndex(): allowed range for index + count "
+ + OUString::number( m_data.size() )
+ + ", got " + OUString::number( index )
+ + " + " + OUString::number( count ),
+ *this, OUString(), 1, Any());
+
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_array.hxx b/connectivity/source/drivers/postgresql/pq_array.hxx
new file mode 100644
index 000000000..b847d646a
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_array.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/sdbc/XArray.hpp>
+
+#include "pq_connection.hxx"
+#include <vector>
+
+namespace pq_sdbc_driver
+{
+
+class Array : public cppu::WeakImplHelper< css::sdbc::XArray >
+{
+ std::vector< css::uno::Any > m_data;
+ css::uno::Reference< css::uno::XInterface > m_owner;
+ css::uno::Reference< css::script::XTypeConverter > m_tc;
+ rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+
+public:
+ Array(
+ const rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ std::vector< css::uno::Any > && data,
+ const css::uno::Reference< css::uno::XInterface > & owner,
+ const css::uno::Reference< css::script::XTypeConverter > &tc) :
+ m_data( std::move(data) ),
+ m_owner( owner ),
+ m_tc( tc ),
+ m_xMutex( mutex )
+ {}
+
+public: // XArray
+
+ // Methods
+ virtual OUString SAL_CALL getBaseTypeName( ) override;
+
+ virtual sal_Int32 SAL_CALL getBaseType( ) override;
+
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getArray(
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getArrayAtIndex(
+ sal_Int32 index,
+ sal_Int32 count,
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL
+ getResultSet(
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSetAtIndex(
+ sal_Int32 index,
+ sal_Int32 count,
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+private:
+ void checkRange( sal_Int32 index, sal_Int32 count );
+};
+
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_baseresultset.cxx b/connectivity/source/drivers/postgresql/pq_baseresultset.cxx
new file mode 100644
index 000000000..9ff5e01e0
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_baseresultset.cxx
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <comphelper/sequence.hxx>
+
+#include "pq_tools.hxx"
+#include "pq_array.hxx"
+#include "pq_baseresultset.hxx"
+
+#include <com/sun/star/script/CannotConvertException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <connectivity/dbconversion.hxx>
+
+using osl::MutexGuard;
+
+
+using com::sun::star::beans::XPropertySetInfo;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+
+using com::sun::star::lang::IllegalArgumentException;
+
+using com::sun::star::sdbc::SQLException;
+
+
+using com::sun::star::beans::Property;
+
+using namespace dbtools;
+
+namespace pq_sdbc_driver
+{
+static ::cppu::IPropertyArrayHelper & getResultSetPropertyArrayHelper()
+{
+ // LEM TODO: this needs to be kept in sync with other, e.g. pq_statics.css:508
+ // Should really share!
+ // At least use for the handles the #define'd values in .hxx file...
+ static ::cppu::OPropertyArrayHelper arrayHelper(
+ Sequence<Property>{
+ Property(
+ "CursorName", 0,
+ ::cppu::UnoType<OUString>::get() , 0 ),
+ Property(
+ "EscapeProcessing", 1,
+ cppu::UnoType<bool>::get() , 0 ),
+ Property(
+ "FetchDirection", 2,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "FetchSize", 3,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "IsBookmarkable", 4,
+ cppu::UnoType<bool>::get() , 0 ),
+ Property(
+ "ResultSetConcurrency", 5,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "ResultSetType", 6,
+ ::cppu::UnoType<sal_Int32>::get() , 0 )},
+ true );
+ return arrayHelper;
+}
+
+BaseResultSet::BaseResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< XInterface > & owner,
+ sal_Int32 rowCount,
+ sal_Int32 colCount,
+ const Reference< css::script::XTypeConverter > & tc )
+ : BaseResultSet_BASE( refMutex->GetMutex() )
+ , OPropertySetHelper( BaseResultSet_BASE::rBHelper )
+ , m_owner( owner )
+ , m_tc( tc )
+ , m_xMutex( refMutex )
+ , m_row( -1 )
+ , m_rowCount( rowCount )
+ , m_fieldCount( colCount )
+ , m_wasNull(false)
+{
+}
+
+// LEM TODO: refMutex->GetMutex() should live longer than OComponentHelper,
+// but calling OComponentHelper::dispose explicitly here calls
+// BaseResultSet::~BaseResultSet in an infinite loop :(
+BaseResultSet::~BaseResultSet()
+{
+}
+
+Any BaseResultSet::queryInterface( const Type & rType )
+{
+ Any aRet = BaseResultSet_BASE::queryInterface(rType);
+ return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
+}
+
+// void BaseResultSet::close( ) throw (SQLException, RuntimeException)
+// {
+// Reference< XInterface > owner;
+// {
+// ResultSetGuard guard(*this);
+// if( m_result )
+// {
+// PQclear(m_result );
+// m_result = 0;
+// m_row = -1;
+// }
+// owner = m_owner;
+// m_owner.clear();
+// }
+// }
+
+Sequence<Type > BaseResultSet::getTypes()
+{
+ static Sequence< Type > collection(
+ ::comphelper::concatSequences(
+ OPropertySetHelper::getTypes(),
+ BaseResultSet_BASE::getTypes()));
+ return collection;
+}
+
+Sequence< sal_Int8> BaseResultSet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// Reference< XResultSetMetaData > BaseResultSet::getMetaData( ) throw (SQLException, RuntimeException)
+// {
+// ResultSetGuard guard(*this);
+// checkClosed();
+// return new ResultSetMetaData( m_xMutex, this, &m_result );
+// }
+
+sal_Bool BaseResultSet::next( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ m_row ++;
+ return m_row < m_rowCount;
+}
+
+sal_Bool BaseResultSet::isBeforeFirst( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_row == -1;
+}
+
+sal_Bool BaseResultSet::isAfterLast( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_row >= m_rowCount;
+}
+
+sal_Bool BaseResultSet::isFirst( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_row == 0 && m_rowCount;
+}
+
+sal_Bool BaseResultSet::isLast( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_row >= 0 && m_row + 1 == m_rowCount;
+}
+
+void BaseResultSet::beforeFirst( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ m_row = -1;
+}
+
+void BaseResultSet::afterLast( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ m_row = m_rowCount;
+}
+
+sal_Bool BaseResultSet::first( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ bool bRet = ( m_rowCount > 0 );
+ if( bRet )
+ m_row = 0;
+ return bRet;
+}
+
+sal_Bool BaseResultSet::last( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ bool bRet = ( m_rowCount > 0 );
+ if( bRet )
+ m_row = m_rowCount -1;
+ return bRet;
+}
+
+sal_Int32 BaseResultSet::getRow( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_row +1;
+}
+
+sal_Bool BaseResultSet::absolute( sal_Int32 row )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ if( row > 0 )
+ {
+ m_row = row -1;
+ if( m_row > m_rowCount )
+ m_row = m_rowCount;
+ }
+ else
+ {
+ m_row = m_rowCount + row;
+ if( m_row < -1 )
+ m_row = -1;
+ }
+ return true;
+}
+
+sal_Bool BaseResultSet::relative( sal_Int32 rows )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ m_row += rows;
+
+ if( m_row > m_rowCount )
+ m_row = m_rowCount;
+ else if ( m_row < -1 )
+ m_row = -1;
+ return true;
+}
+
+sal_Bool BaseResultSet::previous( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ bool bRet = ( m_row != -1 );
+ if( bRet )
+ m_row --;
+ return bRet;
+}
+
+void BaseResultSet::refreshRow( )
+{
+ // TODO: not supported for now
+}
+
+sal_Bool BaseResultSet::rowUpdated( )
+{
+ return false;
+}
+
+sal_Bool BaseResultSet::rowInserted( )
+{
+ return false;
+}
+
+sal_Bool BaseResultSet::rowDeleted( )
+{
+ return false;
+}
+
+Reference< XInterface > BaseResultSet::getStatement()
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return m_owner;
+}
+
+
+//----------------- XRow interface ----------------------------------------------------
+
+sal_Bool BaseResultSet::wasNull( )
+{
+ return m_wasNull;
+}
+
+Any BaseResultSet::convertTo( const Any & val , const Type & type )
+{
+ Any aRet;
+ try
+ {
+ aRet = m_tc->convertTo( val , type );
+ }
+ catch( css::lang::IllegalArgumentException & )
+ {}
+ catch( css::script::CannotConvertException & )
+ {}
+ return aRet;
+}
+
+sal_Bool BaseResultSet::getBoolean( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+
+ OUString str = getString( columnIndex );
+
+ if( str.getLength() > 0 )
+ {
+ switch(str[0])
+ {
+ case '1':
+ case 't':
+ case 'T':
+ case 'y':
+ case 'Y':
+
+ return true;
+ }
+ }
+ return false;
+}
+
+sal_Int8 BaseResultSet::getByte( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ sal_Int8 b = 0;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(b)>::get()) >>= b;
+ return b;
+}
+
+sal_Int16 BaseResultSet::getShort( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ sal_Int16 i = 0;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
+ return i;
+}
+
+OUString BaseResultSet::getString( sal_Int32 columnIndex )
+{
+ MutexGuard guard(m_xMutex->GetMutex());
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ OUString ret;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(ret)>::get() ) >>= ret;
+// printf( "BaseResultSet::getString() %s\n" , OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return ret;
+}
+
+sal_Int32 BaseResultSet::getInt( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ sal_Int32 i = 0;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
+ return i;
+}
+
+sal_Int64 BaseResultSet::getLong( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ sal_Int64 i = 0;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(i)>::get()) >>= i;
+ return i;
+}
+
+float BaseResultSet::getFloat( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+ float f = 0.;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(f)>::get()) >>= f;
+ return f;
+}
+
+double BaseResultSet::getDouble( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ double d = 0.;
+ convertTo( getValue( columnIndex ), cppu::UnoType<decltype(d)>::get()) >>= d;
+ return d;
+}
+
+Sequence< sal_Int8 > BaseResultSet::getBytes( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( columnIndex );
+ checkRowIndex();
+
+ Sequence< sal_Int8 > ret;
+ OUString ustr;
+ if( ! (getValue( columnIndex ) >>= ustr) )
+ m_wasNull = true;
+ else
+ {
+ // if this is a binary, it must contain escaped data !
+ OString val = OUStringToOString( ustr, RTL_TEXTENCODING_ASCII_US );
+
+ size_t length;
+ char * res = reinterpret_cast<char*>(PQunescapeBytea( reinterpret_cast<unsigned char const *>(val.getStr()), &length));
+ ret = Sequence< sal_Int8 > ( reinterpret_cast<sal_Int8*>(res), length );
+ if( res )
+ PQfreemem( res );
+ }
+ return ret;
+}
+
+
+css::util::Date BaseResultSet::getDate( sal_Int32 columnIndex )
+{
+ return DBTypeConversion::toDate( getString( columnIndex ) );
+}
+
+css::util::Time BaseResultSet::getTime( sal_Int32 columnIndex )
+{
+ return DBTypeConversion::toTime( getString( columnIndex ) );
+}
+
+css::util::DateTime BaseResultSet::getTimestamp( sal_Int32 columnIndex )
+{
+ return DBTypeConversion::toDateTime( getString( columnIndex ) );
+}
+
+ // LEM TODO: these look like they are missing an actual implementation
+Reference< css::io::XInputStream > BaseResultSet::getBinaryStream( sal_Int32 /* columnIndex */ )
+{
+ return nullptr;
+}
+
+Reference< css::io::XInputStream > BaseResultSet::getCharacterStream( sal_Int32 /* columnIndex */ )
+{
+ return nullptr;
+}
+
+Any BaseResultSet::getObject(
+ sal_Int32 /* columnIndex */,
+ const Reference< css::container::XNameAccess >& /* typeMap */ )
+{
+ return Any();
+}
+
+Reference< css::sdbc::XRef > BaseResultSet::getRef( sal_Int32 /* columnIndex */ )
+{
+ return Reference< css::sdbc::XRef > ();
+}
+
+Reference< css::sdbc::XBlob > BaseResultSet::getBlob( sal_Int32 /* columnIndex */ )
+{
+ return Reference< css::sdbc::XBlob > ();
+}
+
+Reference< css::sdbc::XClob > BaseResultSet::getClob( sal_Int32 /* columnIndex */ )
+{
+ return Reference< css::sdbc::XClob > ();
+}
+
+Reference< css::sdbc::XArray > BaseResultSet::getArray( sal_Int32 columnIndex )
+{
+ return new Array( m_xMutex, parseArray( getString( columnIndex ) ), *this, m_tc );
+}
+
+::cppu::IPropertyArrayHelper & BaseResultSet::getInfoHelper()
+{
+ return getResultSetPropertyArrayHelper();
+}
+
+sal_Bool BaseResultSet::convertFastPropertyValue(
+ Any & /* rConvertedValue */, Any & /* rOldValue */, sal_Int32 nHandle, const Any& rValue )
+{
+ bool bRet;
+ switch( nHandle )
+ {
+ case BASERESULTSET_CURSOR_NAME:
+ {
+ OUString val;
+ bRet = ( rValue >>= val );
+ m_props[nHandle] <<= val;
+ break;
+ }
+ case BASERESULTSET_ESCAPE_PROCESSING:
+ case BASERESULTSET_IS_BOOKMARKABLE:
+ {
+ bool val(false);
+ bRet = ( rValue >>= val );
+ m_props[nHandle] <<= val;
+ break;
+ }
+ case BASERESULTSET_FETCH_DIRECTION:
+ case BASERESULTSET_FETCH_SIZE:
+ case BASERESULTSET_RESULT_SET_CONCURRENCY:
+ case BASERESULTSET_RESULT_SET_TYPE:
+ {
+ sal_Int32 val;
+ bRet = ( rValue >>= val );
+ m_props[nHandle] <<= val;
+ break;
+ }
+ default:
+ {
+ throw IllegalArgumentException(
+ "pq_resultset: Invalid property handle (" + OUString::number( nHandle ) + ")",
+ *this, 2 );
+ }
+ }
+ return bRet;
+}
+
+
+void BaseResultSet::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,const Any& rValue )
+{
+ m_props[nHandle] = rValue;
+}
+
+void BaseResultSet::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ rValue = m_props[nHandle];
+}
+
+Reference < XPropertySetInfo > BaseResultSet::getPropertySetInfo()
+{
+ return OPropertySetHelper::createPropertySetInfo( getResultSetPropertyArrayHelper() );
+}
+
+void BaseResultSet::disposing()
+{
+ close();
+}
+
+void BaseResultSet::checkColumnIndex(sal_Int32 index )
+{
+ if( index < 1 || index > m_fieldCount )
+ {
+ throw SQLException(
+ "pq_resultset: index out of range ("
+ + OUString::number( index )
+ + ", allowed range is 1 to " + OUString::number( m_fieldCount )
+ + ")",
+ *this, OUString(), 1, Any() );
+ }
+
+}
+
+void BaseResultSet::checkRowIndex()
+{
+ if( m_row < 0 || m_row >= m_rowCount )
+ {
+ throw SQLException(
+ "pq_baseresultset: row index out of range, allowed is 0 to " + OUString::number( m_rowCount -1 )
+ + ", got " + OUString::number( m_row ),
+ *this, OUString(),1, Any() );
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_baseresultset.hxx b/connectivity/source/drivers/postgresql/pq_baseresultset.hxx
new file mode 100644
index 000000000..90e6609a0
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_baseresultset.hxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/component.hxx>
+
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include "pq_connection.hxx"
+
+namespace pq_sdbc_driver
+{
+
+const sal_Int32 BASERESULTSET_CURSOR_NAME = 0;
+const sal_Int32 BASERESULTSET_ESCAPE_PROCESSING = 1;
+const sal_Int32 BASERESULTSET_FETCH_DIRECTION = 2;
+const sal_Int32 BASERESULTSET_FETCH_SIZE = 3;
+const sal_Int32 BASERESULTSET_IS_BOOKMARKABLE = 4;
+const sal_Int32 BASERESULTSET_RESULT_SET_CONCURRENCY = 5;
+const sal_Int32 BASERESULTSET_RESULT_SET_TYPE = 6;
+
+#define BASERESULTSET_SIZE 7
+
+typedef ::cppu::WeakComponentImplHelper< css::sdbc::XCloseable,
+ css::sdbc::XResultSetMetaDataSupplier,
+ css::sdbc::XResultSet,
+ css::sdbc::XRow,
+ css::sdbc::XColumnLocate
+ > BaseResultSet_BASE;
+class BaseResultSet : public BaseResultSet_BASE,
+ public cppu::OPropertySetHelper
+{
+protected:
+ css::uno::Any m_props[BASERESULTSET_SIZE];
+ css::uno::Reference< css::uno::XInterface > m_owner;
+ css::uno::Reference< css::script::XTypeConverter > m_tc;
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ sal_Int32 m_row;
+ sal_Int32 m_rowCount;
+ sal_Int32 m_fieldCount;
+ bool m_wasNull;
+
+protected:
+ /** mutex should be locked before called
+
+ @throws css::sdbc::SQLException
+ @throws css::uno::RuntimeException
+ */
+ virtual void checkClosed() = 0;
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkColumnIndex( sal_Int32 index );
+ void checkRowIndex();
+
+ virtual css::uno::Any getValue( sal_Int32 columnIndex ) = 0;
+ css::uno::Any convertTo(
+ const css::uno::Any &str, const css::uno::Type &type );
+
+protected:
+ BaseResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ sal_Int32 rowCount,
+ sal_Int32 columnCount,
+ const css::uno::Reference< css::script::XTypeConverter > &tc );
+ virtual ~BaseResultSet() override;
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { BaseResultSet_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { BaseResultSet_BASE::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XCloseable
+// virtual void SAL_CALL close( )
+// throw (css::sdbc::SQLException, css::uno::RuntimeException) = 0;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XResultSetMetaDataSupplier
+// virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( )
+// throw (css::sdbc::SQLException, css::uno::RuntimeException) = 0;
+
+public: // XResultSet
+ // Methods
+ virtual sal_Bool SAL_CALL next( ) override;
+ virtual sal_Bool SAL_CALL isBeforeFirst( ) override;
+ virtual sal_Bool SAL_CALL isAfterLast( ) override;
+ virtual sal_Bool SAL_CALL isFirst( ) override;
+ virtual sal_Bool SAL_CALL isLast( ) override;
+ virtual void SAL_CALL beforeFirst( ) override;
+ virtual void SAL_CALL afterLast( ) override;
+ virtual sal_Bool SAL_CALL first( ) override;
+ virtual sal_Bool SAL_CALL last( ) override;
+ virtual sal_Int32 SAL_CALL getRow( ) override;
+ virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) override;
+ virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) override;
+ virtual sal_Bool SAL_CALL previous( ) override;
+ virtual void SAL_CALL refreshRow( ) override;
+ virtual sal_Bool SAL_CALL rowUpdated( ) override;
+ virtual sal_Bool SAL_CALL rowInserted( ) override;
+ virtual sal_Bool SAL_CALL rowDeleted( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement() override;
+
+
+public: // XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject(
+ sal_Int32 columnIndex,
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+
+public: // XColumnLocate
+// virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName )
+// throw (css::sdbc::SQLException, css::uno::RuntimeException) = 0;
+
+public: // OPropertySetHelper
+ virtual cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+
+ void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle ) const override;
+
+ // XPropertySet
+ css::uno::Reference < css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+
+public: // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_connection.cxx b/connectivity/source/drivers/postgresql/pq_connection.cxx
new file mode 100644
index 000000000..6661a97d5
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_connection.cxx
@@ -0,0 +1,571 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <vector>
+#include <string.h>
+
+#include <memory>
+
+#include "pq_connection.hxx"
+#include "pq_statement.hxx"
+#include "pq_tools.hxx"
+#include "pq_preparedstatement.hxx"
+#include "pq_databasemetadata.hxx"
+#include "pq_xtables.hxx"
+#include "pq_xviews.hxx"
+#include "pq_xusers.hxx"
+
+#include <rtl/ref.hxx>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/script/Converter.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+using osl::MutexGuard;
+
+using com::sun::star::container::XNameAccess;
+
+using com::sun::star::lang::XComponent;
+using com::sun::star::lang::IllegalArgumentException;
+
+using com::sun::star::script::Converter;
+using com::sun::star::script::XTypeConverter;
+
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::Any;
+
+using com::sun::star::beans::PropertyValue;
+
+using com::sun::star::sdbc::XCloseable;
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XPreparedStatement;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XDatabaseMetaData;
+
+namespace pq_sdbc_driver
+{
+
+namespace {
+
+// Helper class for statement lifetime management
+class ClosableReference : public cppu::WeakImplHelper< css::uno::XReference >
+{
+ rtl::Reference<Connection> m_conn;
+ ::rtl::ByteSequence m_id;
+public:
+ ClosableReference( const ::rtl::ByteSequence & id , Connection *that )
+ : m_conn( that ), m_id( id )
+ {
+ }
+
+ virtual void SAL_CALL dispose() override
+ {
+ if( m_conn.is() )
+ {
+ m_conn->removeFromWeakMap(m_id);
+ m_conn.clear();
+ }
+ }
+};
+
+}
+
+Connection::Connection(
+ const rtl::Reference< comphelper::RefCountedMutex > &refMutex,
+ const css::uno::Reference< css::uno::XComponentContext > & ctx )
+ : ConnectionBase( refMutex->GetMutex() ),
+ m_ctx( ctx ) ,
+ m_xMutex( refMutex )
+{
+}
+
+Connection::~Connection()
+{
+ if( m_settings.pConnection )
+ {
+ PQfinish( m_settings.pConnection );
+ m_settings.pConnection = nullptr;
+ }
+}
+
+void Connection::close()
+{
+ std::vector< css::uno::Reference< css::sdbc::XCloseable > > vectorCloseable;
+ std::vector< css::uno::Reference< css::lang::XComponent > > vectorDispose;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ // silently ignore, if the connection has been closed already
+ if( m_settings.pConnection )
+ {
+ SAL_INFO("connectivity.postgresql", "closing connection");
+ PQfinish( m_settings.pConnection );
+ m_settings.pConnection = nullptr;
+ }
+
+ vectorDispose.push_back( Reference< XComponent > ( m_settings.users, UNO_QUERY ) );
+ vectorDispose.push_back( Reference< XComponent > ( m_settings.tables , UNO_QUERY ) );
+ vectorDispose.push_back( Reference< XComponent > ( m_meta, UNO_QUERY ) );
+ m_meta.clear();
+ m_settings.tables.clear();
+ m_settings.users.clear();
+
+ for (auto const& statement : m_myStatements)
+ {
+ Reference< XCloseable > r = statement.second;
+ if( r.is() )
+ vectorCloseable.push_back( r );
+ }
+ }
+
+ // close all created statements
+ for (auto const& elem : vectorCloseable)
+ elem->close();
+
+ // close all created statements
+ for (auto const& elem : vectorDispose)
+ {
+ if( elem.is() )
+ elem->dispose();
+ }
+}
+
+
+void Connection::removeFromWeakMap( const ::rtl::ByteSequence & id )
+{
+ // shrink the list !
+ MutexGuard guard( m_xMutex->GetMutex() );
+ WeakHashMap::iterator ii = m_myStatements.find( id );
+ if( ii != m_myStatements.end() )
+ m_myStatements.erase( ii );
+}
+
+Reference< XStatement > Connection::createStatement()
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+
+ rtl::Reference<Statement> stmt = new Statement( m_xMutex, this , &m_settings );
+ ::rtl::ByteSequence id( 16 );
+ rtl_createUuid( reinterpret_cast<sal_uInt8*>(id.getArray()), nullptr, false );
+ m_myStatements[ id ] = Reference< XCloseable > ( stmt );
+ stmt->queryAdapter()->addReference( new ClosableReference( id, this ) );
+ return stmt;
+}
+
+Reference< XPreparedStatement > Connection::prepareStatement( const OUString& sql )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+
+ OString byteSql = OUStringToOString( sql, ConnectionSettings::encoding );
+ rtl::Reference<PreparedStatement> stmt
+ = new PreparedStatement( m_xMutex, this, &m_settings, byteSql );
+
+ ::rtl::ByteSequence id( 16 );
+ rtl_createUuid( reinterpret_cast<sal_uInt8*>(id.getArray()), nullptr, false );
+ m_myStatements[ id ] = Reference< XCloseable > ( stmt );
+ stmt->queryAdapter()->addReference( new ClosableReference( id, this ) );
+ return stmt;
+}
+
+Reference< XPreparedStatement > Connection::prepareCall( const OUString& )
+{
+ throw SQLException(
+ "pq_driver: Callable statements not supported",
+ Reference< XInterface > (), OUString() , 1, Any() );
+}
+
+
+OUString Connection::nativeSQL( const OUString& sql )
+{
+ return sql;
+}
+
+void Connection::setAutoCommit( sal_Bool )
+{
+ // UNSUPPORTED
+}
+
+sal_Bool Connection::getAutoCommit()
+{
+ // UNSUPPORTED
+ return true;
+}
+
+void Connection::commit()
+{
+ // UNSUPPORTED
+}
+
+void Connection::rollback()
+{
+ // UNSUPPORTED
+}
+
+sal_Bool Connection::isClosed()
+{
+ return m_settings.pConnection == nullptr;
+}
+
+Reference< XDatabaseMetaData > Connection::getMetaData()
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ if( ! m_meta.is() )
+ m_meta = new DatabaseMetaData( m_xMutex, this, &m_settings );
+ return m_meta;
+}
+
+void Connection::setReadOnly( sal_Bool )
+{
+ // UNSUPPORTED
+
+}
+
+sal_Bool Connection::isReadOnly()
+{
+ // UNSUPPORTED
+ return false;
+}
+
+void Connection::setCatalog( const OUString& )
+{
+ // UNSUPPORTED
+}
+
+OUString Connection::getCatalog()
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ if( m_settings.pConnection == nullptr )
+ {
+ throw SQLException( "pq_connection: connection is closed", *this,
+ OUString(), 1, Any() );
+ }
+ char * p = PQdb(m_settings.pConnection );
+ return OUString( p, strlen(p) , ConnectionSettings::encoding );
+}
+
+void Connection::setTransactionIsolation( sal_Int32 )
+{
+ // UNSUPPORTED
+}
+
+sal_Int32 Connection::getTransactionIsolation()
+{
+ // UNSUPPORTED
+ return 0;
+}
+
+Reference< XNameAccess > Connection::getTypeMap()
+{
+ Reference< XNameAccess > t;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ t = m_typeMap;
+ }
+ return t;
+}
+
+void Connection::setTypeMap( const Reference< XNameAccess >& typeMap )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ m_typeMap = typeMap;
+}
+Any Connection::getWarnings()
+{
+ return Any();
+}
+
+void Connection::clearWarnings()
+{
+}
+
+namespace {
+
+class cstr_vector
+{
+ std::vector<char*> values;
+ std::vector<bool> acquired;
+public:
+ cstr_vector () { values.reserve(8); acquired.reserve(8); }
+ ~cstr_vector ()
+ {
+ OSL_ENSURE(values.size() == acquired.size(), "pq_connection: cstr_vector values and acquired size mismatch");
+ std::vector<bool>::const_iterator pa = acquired.begin();
+ for( const auto& v : values )
+ {
+ if (*pa)
+ free(v);
+ ++pa;
+ }
+ }
+ void push_back(const char* s, __sal_NoAcquire)
+ {
+ values.push_back(const_cast<char*>(s));
+ acquired.push_back(false);
+ }
+ void push_back(char* s)
+ {
+ values.push_back(s);
+ acquired.push_back(true);
+ }
+ // This const_cast is there for compatibility with PostgreSQL <= 9.1;
+ // PostgreSQL >= 9.2 has the right const qualifiers in the headers
+ // for a return type of "char const*const*".
+ char const** c_array() const { return const_cast <const char**>(values.data()); }
+};
+
+}
+
+static void properties2arrays( const Sequence< PropertyValue > & args,
+ const Reference< XTypeConverter> &tc,
+ rtl_TextEncoding enc,
+ cstr_vector &keywords,
+ cstr_vector &values)
+{
+ // LEM TODO: can we just blindly take all properties?
+ // I.e. they are prefiltered to have only relevant ones?
+ // Else, at least support all keywords from
+ // http://www.postgresql.org/docs/9.0/interactive/libpq-connect.html
+
+ static const char* keyword_list[] = {
+ "password",
+ "user",
+ "port",
+ "dbname",
+ "connect_timeout",
+ "options",
+ "requiressl"
+ };
+
+ for( PropertyValue const & prop : args )
+ {
+ bool append = false;
+ for(const char* j : keyword_list)
+ {
+ if( prop.Name.equalsIgnoreAsciiCaseAscii( j ))
+ {
+ keywords.push_back( j, SAL_NO_ACQUIRE );
+ append = true;
+ break;
+ }
+ }
+
+ if( append )
+ {
+ OUString value;
+ tc->convertTo( prop.Value, cppu::UnoType<decltype(value)>::get() ) >>= value;
+ char *v = strdup(OUStringToOString(value, enc).getStr());
+ values.push_back ( v );
+ }
+ else
+ {
+ // ignore for now
+ SAL_WARN("connectivity.postgresql", "sdbc-postgresql: unknown argument '" << prop.Name << "' having value: " << prop.Value );
+ }
+ }
+}
+
+void Connection::initialize( const Sequence< Any >& aArguments )
+{
+ OUString url;
+ Sequence< PropertyValue > args;
+
+ Reference< XTypeConverter > tc( Converter::create(m_ctx) );
+ if( ! tc.is() )
+ {
+ throw RuntimeException(
+ "pq_driver: Couldn't instantiate converter service" );
+ }
+ if( aArguments.getLength() != 2 )
+ {
+ throw IllegalArgumentException(
+ "pq_driver: expected 2 arguments, got " + OUString::number( aArguments.getLength( ) ),
+ Reference< XInterface > () , 0 );
+ }
+
+ if( ! (aArguments[0] >>= url) )
+ {
+ throw IllegalArgumentException(
+ "pq_driver: expected string as first argument, got "
+ + aArguments[0].getValueType().getTypeName(),
+ *this, 0 );
+ }
+
+ tc->convertTo( aArguments[1], cppu::UnoType<decltype(args)>::get() ) >>= args;
+
+ OString o;
+ int nColon = url.indexOf( ':' );
+ if( nColon != -1 )
+ {
+ nColon = url.indexOf( ':' , 1+ nColon );
+ if( nColon != -1 )
+ {
+ o = rtl::OUStringToOString( url.subView(nColon+1), ConnectionSettings::encoding );
+ }
+ }
+ {
+ cstr_vector keywords;
+ cstr_vector values;
+
+ if ( o.getLength() > 0 )
+ {
+ char *err;
+ const std::unique_ptr<PQconninfoOption, deleter_from_fn<PQconninfoFree>>
+ oOpts(PQconninfoParse(o.getStr(), &err));
+ if (oOpts == nullptr)
+ {
+ OUString errorMessage;
+ if ( err != nullptr)
+ {
+ errorMessage = OUString( err, strlen(err), ConnectionSettings::encoding );
+ PQfreemem(err);
+ }
+ else
+ errorMessage = "#no error message#";
+ // HY092 is "Invalid attribute/option identifier."
+ // Just the most likely error; the error might be HY024 "Invalid attribute value".
+ throw SQLException(
+ "Error in database URL '" + url + "':\n" + errorMessage,
+ *this, "HY092", 5, Any() );
+ }
+
+ for ( PQconninfoOption * opt = oOpts.get(); opt->keyword != nullptr; ++opt)
+ {
+ if ( opt->val != nullptr )
+ {
+ keywords.push_back(strdup(opt->keyword));
+ values.push_back(strdup(opt->val));
+ }
+ }
+ }
+ properties2arrays( args , tc, ConnectionSettings::encoding, keywords, values );
+ keywords.push_back(nullptr, SAL_NO_ACQUIRE);
+ values.push_back(nullptr, SAL_NO_ACQUIRE);
+
+ m_settings.pConnection = PQconnectdbParams( keywords.c_array(), values.c_array(), 0 );
+ }
+ if( ! m_settings.pConnection )
+ throw RuntimeException("pq_driver: out of memory" );
+ if( PQstatus( m_settings.pConnection ) == CONNECTION_BAD )
+ {
+ const char * error = PQerrorMessage( m_settings.pConnection );
+ OUString errorMessage( error, strlen( error) , RTL_TEXTENCODING_ASCII_US );
+ PQfinish( m_settings.pConnection );
+ m_settings.pConnection = nullptr;
+ throw SQLException(
+ "Couldn't establish database connection to '" + url + "'\n"
+ + errorMessage,
+ *this, errorMessage, CONNECTION_BAD, Any() );
+ }
+ PQsetClientEncoding( m_settings.pConnection, "UNICODE" );
+ char *p = PQuser( m_settings.pConnection );
+ m_settings.user = OUString( p, strlen(p), RTL_TEXTENCODING_UTF8);
+ p = PQdb( m_settings.pConnection );
+ m_settings.catalog = OUString( p, strlen(p), RTL_TEXTENCODING_UTF8);
+ m_settings.tc = tc;
+
+ SAL_INFO("connectivity.postgresql", "connection to '" << url << "' successfully opened");
+}
+
+void Connection::disposing()
+{
+ close();
+}
+
+void Connection::checkClosed()
+{
+ if( !m_settings.pConnection )
+ throw SQLException( "pq_connection: Connection already closed",
+ *this, OUString(), 1, Any() );
+}
+
+Reference< XNameAccess > Connection::getTables()
+{
+ SAL_INFO("connectivity.postgresql", "Connection::getTables() got called");
+ MutexGuard guard( m_xMutex->GetMutex() );
+ if( !m_settings.tables.is() )
+ m_settings.tables = Tables::create( m_xMutex, this, &m_settings , &m_settings.pTablesImpl);
+ else
+ // TODO: how to overcome the performance problem ?
+ Reference< css::util::XRefreshable > ( m_settings.tables, UNO_QUERY_THROW )->refresh();
+ return m_settings.tables;
+}
+
+Reference< XNameAccess > Connection::getViews()
+{
+ SAL_INFO("connectivity.postgresql", "Connection::getViews() got called");
+ MutexGuard guard( m_xMutex->GetMutex() );
+ if( !m_settings.views.is() )
+ m_settings.views = Views::create( m_xMutex, this, &m_settings, &(m_settings.pViewsImpl) );
+ else
+ // TODO: how to overcome the performance problem ?
+ Reference< css::util::XRefreshable > ( m_settings.views, UNO_QUERY_THROW )->refresh();
+ return m_settings.views;
+}
+
+
+Reference< XNameAccess > Connection::getUsers()
+{
+ SAL_INFO("connectivity.postgresql", "Connection::getUsers() got called");
+
+ MutexGuard guard( m_xMutex->GetMutex() );
+ if( !m_settings.users.is() )
+ m_settings.users = Users::create( m_xMutex, this, &m_settings );
+ return m_settings.users;
+}
+
+} // end namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+connectivity_postgresql_Connection_get_implementation(
+ css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
+{
+ ::rtl::Reference< comphelper::RefCountedMutex > ref = new comphelper::RefCountedMutex;
+ return cppu::acquire(new pq_sdbc_driver::Connection( ref, context ));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_connection.hxx b/connectivity/source/drivers/postgresql/pq_connection.hxx
new file mode 100644
index 000000000..f30483f70
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_connection.hxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <config_lgpl.h>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/sdbcx/XUsersSupplier.hpp>
+#include <com/sun/star/sdbcx/XViewsSupplier.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/byteseq.hxx>
+
+#include <comphelper/refcountedmutex.hxx>
+
+#include <cppuhelper/weakref.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <functional>
+
+#include <libpq-fe.h>
+#include <unordered_map>
+
+#include "pq_xtables.hxx"
+#include "pq_xviews.hxx"
+
+namespace pq_sdbc_driver
+{
+struct ConnectionSettings;
+struct ConnectionSettings
+{
+ ConnectionSettings() :
+ pConnection(nullptr),
+ maxNameLen(0),
+ maxIndexKeys(0)
+ {}
+ static const rtl_TextEncoding encoding = RTL_TEXTENCODING_UTF8;
+ PGconn *pConnection;
+ sal_Int32 maxNameLen;
+ sal_Int32 maxIndexKeys;
+ css::uno::Reference< css::script::XTypeConverter > tc;
+ css::uno::Reference< css::container::XNameAccess > tables;
+ css::uno::Reference< css::container::XNameAccess > users;
+ css::uno::Reference< css::container::XNameAccess > views;
+ rtl::Reference<Tables> pTablesImpl; // needed to implement renaming of tables / views
+ rtl::Reference<Views> pViewsImpl; // needed to implement renaming of tables / views
+ OUString user;
+ OUString catalog;
+};
+
+
+typedef cppu::WeakComponentImplHelper<
+ css::sdbc::XConnection,
+ css::sdbc::XWarningsSupplier,
+ css::lang::XInitialization,
+ css::sdbcx::XTablesSupplier,
+ css::sdbcx::XViewsSupplier,
+ css::sdbcx::XUsersSupplier > ConnectionBase;
+
+// some types
+struct HashByteSequence
+{
+ sal_Int32 operator () ( const ::rtl::ByteSequence & seq ) const
+ {
+ return *reinterpret_cast<sal_Int32 const *>(seq.getConstArray());
+ }
+};
+
+typedef std::unordered_map<
+ ::rtl::ByteSequence,
+ css::uno::WeakReference< css::sdbc::XCloseable >,
+ HashByteSequence > WeakHashMap;
+
+
+typedef std::unordered_map
+<
+ sal_Int32,
+ OUString
+> Int2StringMap;
+
+class Connection : public ConnectionBase
+{
+ css::uno::Reference< css::uno::XComponentContext > m_ctx;
+ css::uno::Reference< css::container::XNameAccess > m_typeMap;
+ ConnectionSettings m_settings;
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_meta;
+ WeakHashMap m_myStatements;
+
+private:
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkClosed();
+
+public:
+ Connection(
+ const rtl::Reference< comphelper::RefCountedMutex > &refMutex,
+ const css::uno::Reference< css::uno::XComponentContext > & ctx );
+
+ virtual ~Connection( ) override;
+
+public: // XCloseable
+ virtual void SAL_CALL close() override;
+
+public: // XConnection
+
+ virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement( ) override ;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement(
+ const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall(
+ const OUString& sql ) override;
+ virtual OUString SAL_CALL nativeSQL( const OUString& sql ) override;
+ virtual void SAL_CALL setAutoCommit( sal_Bool autoCommit ) override;
+ virtual sal_Bool SAL_CALL getAutoCommit( ) override;
+ virtual void SAL_CALL commit( ) override;
+ virtual void SAL_CALL rollback( ) override;
+ virtual sal_Bool SAL_CALL isClosed( ) override;
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) override;
+ virtual void SAL_CALL setReadOnly( sal_Bool readOnly ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual void SAL_CALL setCatalog( const OUString& catalog ) override;
+ virtual OUString SAL_CALL getCatalog( ) override;
+ virtual void SAL_CALL setTransactionIsolation( sal_Int32 level ) override;
+ virtual sal_Int32 SAL_CALL getTransactionIsolation( ) override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap( ) override;
+ virtual void SAL_CALL setTypeMap(
+ const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+
+public: // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+public: // XInitialization
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+public: // XTablesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+
+public: // XUsersSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getUsers( ) override;
+
+public: // XViewsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getViews( ) override;
+
+public:
+ virtual void SAL_CALL disposing() override;
+
+public: // helper function
+ void removeFromWeakMap( const ::rtl::ByteSequence & seq );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx b/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx
new file mode 100644
index 000000000..7da57d1b6
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_databasemetadata.cxx
@@ -0,0 +1,2511 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Some portions were adapted from JDBC PostgreSQL driver:
+ *
+ * Copyright (c) 2004-2008, PostgreSQL Global Development Group
+ *
+ * Licence of original JDBC driver code:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of the PostgreSQL Global Development Group nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************/
+
+#include <algorithm>
+#include <string_view>
+
+#include <sal/log.hxx>
+#include "pq_databasemetadata.hxx"
+#include "pq_driver.hxx"
+#include "pq_sequenceresultset.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+#include <o3tl/string_view.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/macros.h>
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/IndexType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+
+using ::osl::MutexGuard;
+
+
+using namespace com::sun::star::sdbc;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+
+namespace pq_sdbc_driver
+{
+// These are pre-processor versions of KeyRule.idl declarations
+// These are inherited from JDBC, and thus won't change anytime soon.
+// Having them as pre-processor definitions allows to include them
+// into compile-time strings (through SAL_STRINGIFY), which can be passed to ASCII_STR.
+// That is without resorting to horrendous hacks in template meta-programming.
+#define KEYRULE_CASCADE 0
+#define KEYRULE_RESTRICT 1
+#define KEYRULE_SET_NULL 2
+#define KEYRULE_NO_ACTION 4
+#define KEYRULE_SET_DEFAULT 4
+// Ditto for Deferrability.idl
+#define DEFERRABILITY_INITIALLY_DEFERRED 5
+#define DEFERRABILITY_INITIALLY_IMMEDIATE 6
+#define DEFERRABILITY_NONE 7
+
+DatabaseMetaData::DatabaseMetaData(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : m_xMutex( refMutex ),
+ m_pSettings( pSettings ),
+ m_origin( origin ),
+ m_getIntSetting_stmt ( m_origin->prepareStatement("SELECT setting FROM pg_catalog.pg_settings WHERE name=?") )
+{
+ init_getReferences_stmt();
+ init_getPrivs_stmt();
+}
+
+sal_Bool DatabaseMetaData::allProceduresAreCallable( )
+{
+ // TODO
+ return false;
+}
+
+sal_Bool DatabaseMetaData::allTablesAreSelectable( )
+{
+ return true;
+}
+
+OUString DatabaseMetaData::getURL( )
+{
+ // TODO
+ // LEM TODO: implement
+ return OUString();
+}
+
+OUString DatabaseMetaData::getUserName( )
+{
+ return m_pSettings->user;
+}
+
+sal_Bool DatabaseMetaData::isReadOnly( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::nullsAreSortedHigh( )
+{
+ // Whether NULL values are considered, for sorting purposes, LARGER than any other value.
+ // Specification: http://download.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#nullsAreSortedHigh()
+ // PostgreSQL behaviour: http://www.postgresql.org/docs/9.1/static/queries-order.html
+ return true;
+}
+
+sal_Bool DatabaseMetaData::nullsAreSortedLow( )
+{
+ return ! nullsAreSortedHigh();
+}
+
+sal_Bool DatabaseMetaData::nullsAreSortedAtStart( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::nullsAreSortedAtEnd( )
+{
+ return false;
+}
+
+OUString DatabaseMetaData::getDatabaseProductName( )
+{
+ return "PostgreSQL";
+}
+
+OUString DatabaseMetaData::getDatabaseProductVersion( )
+{
+ return OUString::createFromAscii( PQparameterStatus( m_pSettings->pConnection, "server_version" ) );
+}
+OUString DatabaseMetaData::getDriverName( )
+{
+ return "postgresql-sdbc";
+}
+
+OUString DatabaseMetaData::getDriverVersion( )
+{
+ return PQ_SDBC_DRIVER_VERSION;
+}
+
+sal_Int32 DatabaseMetaData::getDriverMajorVersion( )
+{
+ return PQ_SDBC_MAJOR;
+}
+
+sal_Int32 DatabaseMetaData::getDriverMinorVersion( )
+{
+ return PQ_SDBC_MINOR;
+}
+
+sal_Bool DatabaseMetaData::usesLocalFiles( )
+{
+ // LEM TODO:
+ // https://wiki.documentfoundation.org/Documentation/DevGuide/Database_Access#XDatabaseMetaData_Interface
+ // says "Returns true when the catalog name of the
+ // database should not appear in the DatasourceBrowser
+ // of LibreOffice API, otherwise false is returned."
+ // So, hmmm, think about it.
+ return false;
+}
+
+sal_Bool DatabaseMetaData::usesLocalFilePerTable( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsMixedCaseIdentifiers( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::storesUpperCaseIdentifiers( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::storesLowerCaseIdentifiers( )
+{
+ return true;
+}
+
+
+sal_Bool DatabaseMetaData::storesMixedCaseIdentifiers( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::supportsMixedCaseQuotedIdentifiers( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::storesUpperCaseQuotedIdentifiers( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::storesLowerCaseQuotedIdentifiers( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::storesMixedCaseQuotedIdentifiers( )
+{
+ return false;
+}
+
+
+OUString DatabaseMetaData::getIdentifierQuoteString( )
+{
+ return "\"";
+}
+
+OUString DatabaseMetaData::getSQLKeywords( )
+{
+ // In Java 6, this is all keywords that are not SQL:2003
+ // In Java 2 v1.4 and as per LibreOffice SDK doc, this is all keywords that are not SQL92
+ // I understand this to mean "reserved keywords" only.
+ // See http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
+ // LEM TODO: consider using pg_get_keywords(), filter on catcode
+ return
+ "ANALYSE,"
+ "ANALYZE,"
+ "ARRAY," //SQL:1999
+ "ASYMMETRIC," //SQL:2003
+ "BINARY," //SQL:1999
+ "CONCURRENTLY,"
+ "CURRENT_CATALOG," //SQL:2008
+ "CURRENT_ROLE," //SQL:1999
+ "CURRENT_SCHEMA," //SQL:2008
+ "DO,"
+ "FREEZE,"
+ "ILIKE,"
+ "ISNULL,"
+ "LIMIT," //SQL:1999; non-reserved in SQL:2003
+ "LOCALTIME," //SQL:1999
+ "LOCALTIMESTAMP," //SQL:1999
+ "NOTNULL,"
+ "OFFSET," //SQL:2008
+ "OVER," //SQL:2003
+ "PLACING," //non-reserved in SQL:2003
+ "RETURNING," //non-reserved in SQL:2008
+ "SIMILAR," //SQL:2003
+ "VARIADIC,"
+ "VERBOSE,"
+ "WINDOW" //SQL:2003
+ ;
+}
+OUString DatabaseMetaData::getNumericFunctions( )
+{
+ // See https://www.postgresql.org/docs/9.1/static/functions-math.html
+ // LEM TODO: Err... https://wiki.documentfoundation.org/Documentation/DevGuide/Database_Access#Support_Scalar_Functions
+ // says this should be "Open Group CLI" names, not PostgreSQL names.
+ // Currently this is just a list of supported functions in PostgreSQL, with PostgreSQL names.
+ // And it is my job to map from Open Group CLI names/syntax to PostgreSQL names/syntax. Where? By parsing the SQL???
+ // Should look at what the JDBC driver is doing.
+ return
+ "abs,"
+ "cbrt,"
+ "ceil,"
+ "ceiling,"
+ "degrees,"
+ "div,"
+ "exp,"
+ "floor,"
+ "ln,"
+ "log,"
+ "mod,"
+ "pi,"
+ "power,"
+ "radians,"
+ "random,"
+ "round,"
+ "setseed,"
+ "sign,"
+ "sqrt,"
+ "trunc,"
+ "width_bucket,"
+ "acos,"
+ "asin,"
+ "atan,"
+ "atan2,"
+ "cos,"
+ "cot,"
+ "sin,"
+ "tan"
+ ;
+}
+
+OUString DatabaseMetaData::getStringFunctions( )
+{
+ // See http://www.postgresql.org/docs/9.1/static/functions-string.html
+ return
+ "bit_length,"
+ "char_length,"
+ "character_length,"
+ "lower,"
+ "octet_length,"
+ "overlay,"
+ "position,"
+ "substring,"
+ "trim,"
+ "upper,"
+ "ascii,"
+ "btrim,"
+ "chr,"
+ "concat,"
+ "concat_ws,"
+ "convert,"
+ "convert_from,"
+ "convert_to,"
+ "decode,"
+ "encode,"
+ "format,"
+ "initcap,"
+ "left,"
+ "length,"
+ "lpad,"
+ "ltrim,"
+ "md5,"
+ "pg_client_encoding,"
+ "quote_ident,"
+ "quote_literal,"
+ "quote_nullable,"
+ "regexp_matches,"
+ "regexp_replace,"
+ "regexp_split_to_array,"
+ "regexp_split_to_table,"
+ "repeat,"
+ "replace,"
+ "reverse,"
+ "right,"
+ "rpad,"
+ "rtrim,"
+ "split_part,"
+ "strpos,"
+ "substr,"
+ "to_ascii,"
+ "to_hex,"
+ "translate"
+ ;
+}
+
+OUString DatabaseMetaData::getSystemFunctions( )
+{
+ // See http://www.postgresql.org/docs/9.1/static/functions-info.html
+ // and http://www.postgresql.org/docs/9.1/static/functions-admin.html
+ return
+ "current_catalog,"
+ "current_database,"
+ "current_query,"
+ "current_schema,"
+ "current_schemas,"
+ "current_user,"
+ "inet_client_addr,"
+ "inet_client_port,"
+ "inet_server_addr,"
+ "inet_server_port,"
+ "pg_backend_pid,"
+ "pg_conf_load_time,"
+ "pg_is_other_temp_schema,"
+ "pg_listening_channels,"
+ "pg_my_temp_schema,"
+ "pg_postmaster_start_time,"
+ "session_user,"
+ "user,"
+ "version,"
+ "has_any_column_privilege,"
+ "has_any_column_privilege,"
+ "has_any_column_privilege,"
+ "has_column_privilege,"
+ "has_database_privilege,"
+ "has_foreign_data_wrapper_privilege,"
+ "has_function_privilege,"
+ "has_language_privilege,"
+ "has_schema_privilege,"
+ "has_sequence_privilege,"
+ "has_server_privilege,"
+ "has_table_privilege,"
+ "has_tablespace_privilege,"
+ "pg_has_role,"
+ "pg_collation_is_visible,"
+ "pg_conversion_is_visible,"
+ "pg_function_is_visible,"
+ "pg_opclass_is_visible,"
+ "pg_operator_is_visible,"
+ "pg_table_is_visible,"
+ "pg_ts_config_is_visible,"
+ "pg_ts_dict_is_visible,"
+ "pg_ts_parser_is_visible,"
+ "pg_ts_template_is_visible,"
+ "pg_type_is_visible,"
+ "format_type,"
+ "pg_describe_object,"
+ "pg_get_constraintdef,"
+ "pg_get_expr,"
+ "pg_get_functiondef,"
+ "pg_get_function_arguments,"
+ "pg_get_function_identity_arguments,"
+ "pg_get_function_result,"
+ "pg_get_indexdef,"
+ "pg_get_keywords,"
+ "pg_get_ruledef,"
+ "pg_get_serial_sequence,"
+ "pg_get_triggerdef,"
+ "pg_get_userbyid,"
+ "pg_get_viewdef,"
+ "pg_options_to_table,"
+ "pg_tablespace_databases,"
+ "pg_typeof,"
+ "col_description,"
+ "obj_description,"
+ "shobj_description,"
+ "txid_current,"
+ "txid_current_snapshot,"
+ "txid_snapshot_xip,"
+ "txid_snapshot_xmax,"
+ "txid_snapshot_xmin,"
+ "txid_visible_in_snapshot,"
+ "xmin,"
+ "xmax,"
+ "xip_list,"
+ "current_setting,"
+ "set_config,"
+ "pg_cancel_backend,"
+ "pg_reload_conf,"
+ "pg_rotate_logfile,"
+ "pg_terminate_backend,"
+ "pg_create_restore_point,"
+ "pg_current_xlog_insert_location,"
+ "pg_current_xlog_location,"
+ "pg_start_backup,"
+ "pg_stop_backup,"
+ "pg_switch_xlog,"
+ "pg_xlogfile_name,"
+ "pg_xlogfile_name_offset,"
+ "pg_is_in_recovery,"
+ "pg_last_xlog_receive_location,"
+ "pg_last_xlog_replay_location,"
+ "pg_last_xact_replay_timestamp,"
+ "pg_is_xlog_replay_paused,"
+ "pg_xlog_replay_pause,"
+ "pg_xlog_replay_resume,"
+ "pg_column_size,"
+ "pg_database_size,"
+ "pg_indexes_size,"
+ "pg_relation_size,"
+ "pg_size_pretty,"
+ "pg_table_size,"
+ "pg_tablespace_size,"
+ "pg_tablespace_size,"
+ "pg_total_relation_size,"
+ "pg_relation_filenode,"
+ "pg_relation_filepath,"
+ "pg_ls_dir,"
+ "pg_read_file,"
+ "pg_read_binary_file,"
+ "pg_stat_file,"
+ "pg_advisory_lock,"
+ "pg_advisory_lock_shared,"
+ "pg_advisory_unlock,"
+ "pg_advisory_unlock_all,"
+ "pg_advisory_unlock_shared,"
+ "pg_advisory_xact_lock,"
+ "pg_advisory_xact_lock_shared,"
+ "pg_try_advisory_lock,"
+ "pg_try_advisory_lock_shared,"
+ "pg_try_advisory_xact_lock,"
+ "pg_try_advisory_xact_lock_shared,"
+ "pg_sleep"
+ ;
+}
+OUString DatabaseMetaData::getTimeDateFunctions( )
+{
+ // TODO
+ return
+ "age,"
+ "age,"
+ "clock_timestamp,"
+ "current_date,"
+ "current_time,"
+ "current_timestamp,"
+ "date_part,"
+ "date_part,"
+ "date_trunc,"
+ "extract,"
+ "extract,"
+ "isfinite,"
+ "isfinite,"
+ "isfinite,"
+ "justify_days,"
+ "justify_hours,"
+ "justify_interval,"
+ "localtime,"
+ "localtimestamp,"
+ "now,"
+ "statement_timestamp,"
+ "timeofday,"
+ "transaction_timestamp,"
+ ;
+}
+OUString DatabaseMetaData::getSearchStringEscape( )
+{
+ return "\\";
+}
+OUString DatabaseMetaData::getExtraNameCharacters( )
+{
+ return "$";
+}
+
+sal_Bool DatabaseMetaData::supportsAlterTableWithAddColumn( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsAlterTableWithDropColumn( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsColumnAliasing( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::nullPlusNonNullIsNull( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsTypeConversion( )
+{
+ // LEM: this is specifically whether the "CONVERT" function is supported
+ // It seems that in PostgreSQL, that function is only for string encoding, so no.
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsConvert( sal_Int32, sal_Int32 )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsTableCorrelationNames( )
+{
+ // LEM: A correlation name is "bar" in "SELECT foo FROM qux [AS] bar WHERE ..."
+ return true;
+}
+
+
+sal_Bool DatabaseMetaData::supportsDifferentTableCorrelationNames( )
+{
+ return false;
+}
+sal_Bool DatabaseMetaData::supportsExpressionsInOrderBy( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsOrderByUnrelated( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsGroupBy( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsGroupByUnrelated( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsGroupByBeyondSelect( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsLikeEscapeClause( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsMultipleResultSets( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsMultipleTransactions( )
+{
+ // Allows multiple transactions open at once (on different connections!)
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsNonNullableColumns( )
+{
+ return true;
+}
+
+
+sal_Bool DatabaseMetaData::supportsMinimumSQLGrammar( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsCoreSQLGrammar( )
+{
+ // LEM: jdbc driver says not, although the comments in it seem old
+ // fdo#45249 Base query design won't use any aggregate function
+ // (except COUNT(*) unless we say yes, so say yes.
+ // Actually, Base assumes *also* support for aggregate functions "collect, fusion, intersection"
+ // as soon as supportsCoreSQLGrammar() returns true.
+ // Those are *not* Core SQL, though. They are in optional feature S271 "Basic multiset support"
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsExtendedSQLGrammar( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsANSI92EntryLevelSQL( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsANSI92IntermediateSQL( )
+{
+ // LEM: jdbc driver says not, although the comments in it seem old
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsANSI92FullSQL( )
+{
+ // LEM: jdbc driver says not, although the comments in it seem old
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsIntegrityEnhancementFacility( )
+{
+ // LEM: jdbc driver says yes, although comment says they are not sure what this means...
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsOuterJoins( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsFullOuterJoins( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsLimitedOuterJoins( )
+{
+ return true;
+}
+
+
+OUString DatabaseMetaData::getSchemaTerm( )
+{
+ return "SCHEMA";
+}
+
+OUString DatabaseMetaData::getProcedureTerm( )
+{
+ return "function";
+}
+
+OUString DatabaseMetaData::getCatalogTerm( )
+{
+ return "DATABASE";
+}
+
+sal_Bool DatabaseMetaData::isCatalogAtStart( )
+{
+ return true;
+}
+
+OUString DatabaseMetaData::getCatalogSeparator( )
+{
+ return ".";
+}
+
+sal_Bool DatabaseMetaData::supportsSchemasInDataManipulation( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSchemasInProcedureCalls( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSchemasInTableDefinitions( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSchemasInIndexDefinitions( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSchemasInPrivilegeDefinitions( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsCatalogsInDataManipulation( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsCatalogsInProcedureCalls( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsCatalogsInTableDefinitions( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::supportsCatalogsInIndexDefinitions( )
+{
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions( )
+{
+ return false;
+}
+
+
+// LEM TODO: positioned (through cursor) updates and deletes seem
+// to be supported; see {UPDATE,DELETE} /table/ (...) WHERE CURRENT OF /cursor_name/" syntax
+// and http://www.postgresql.org/docs/9.1/static/view-pg-cursors.html
+// http://www.postgresql.org/docs/9.1/static/libpq-example.html actually uses a cursor :)
+sal_Bool DatabaseMetaData::supportsPositionedDelete( )
+{
+ // LEM: jdbc driver says not, although the comments in it seem old
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsPositionedUpdate( )
+{
+ // LEM: jdbc driver says not, although the comments in it seem old
+ return false;
+}
+
+
+sal_Bool DatabaseMetaData::supportsSelectForUpdate( )
+{
+ return true;
+}
+
+
+sal_Bool DatabaseMetaData::supportsStoredProcedures( )
+{
+ return true;
+}
+
+
+sal_Bool DatabaseMetaData::supportsSubqueriesInComparisons( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSubqueriesInExists( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSubqueriesInIns( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsSubqueriesInQuantifieds( )
+{
+ // LEM: jdbc driver says yes, although comment says they don't know what this means...
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsCorrelatedSubqueries( )
+{
+ return true;
+}
+sal_Bool DatabaseMetaData::supportsUnion( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsUnionAll( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossCommit( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsOpenCursorsAcrossRollback( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossCommit( )
+{
+ return true;
+}
+sal_Bool DatabaseMetaData::supportsOpenStatementsAcrossRollback( )
+{
+ return true;
+}
+
+sal_Int32 DatabaseMetaData::getMaxBinaryLiteralLength( )
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxCharLiteralLength( )
+{
+ return 0;
+}
+
+// Copied / adapted / simplified from JDBC driver
+sal_Int32 DatabaseMetaData::getIntSetting(const OUString& settingName)
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ Reference< XParameters > params(m_getIntSetting_stmt, UNO_QUERY_THROW );
+ params->setString(1, settingName );
+ Reference< XResultSet > rs = m_getIntSetting_stmt->executeQuery();
+ Reference< XRow > xRow( rs , UNO_QUERY_THROW );
+ OSL_VERIFY(rs->next());
+ OSL_ENSURE(rs->isFirst(), "postgresql-sdbc DatabaseMetaData getIntSetting not on first row");
+ OSL_ENSURE(rs->isLast(), "postgresql-sdbc DatabaseMetaData getIntSetting not on last row");
+ return xRow->getInt(1);
+}
+
+sal_Int32 DatabaseMetaData::getMaxNameLength()
+{
+ if ( m_pSettings->maxNameLen == 0)
+ m_pSettings->maxNameLen = getIntSetting( "max_identifier_length" );
+ OSL_ENSURE(m_pSettings->maxNameLen, "postgresql-sdbc: maxNameLen is zero");
+ return m_pSettings->maxNameLen;
+}
+
+sal_Int32 DatabaseMetaData::getMaxIndexKeys()
+{
+ if ( m_pSettings->maxIndexKeys == 0)
+ m_pSettings->maxIndexKeys = getIntSetting("max_index_keys");
+ OSL_ENSURE(m_pSettings->maxIndexKeys, "postgresql-sdbc: maxIndexKeys is zero");
+ return m_pSettings->maxIndexKeys;
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnsInGroupBy( )
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnsInIndex( )
+{
+ return getMaxIndexKeys();
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnsInOrderBy( )
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnsInSelect( )
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxColumnsInTable( )
+{
+ return 1600;
+}
+
+sal_Int32 DatabaseMetaData::getMaxConnections( )
+{
+ // LEM: The JDBC driver returns an arbitrary 8192; truth is as much as OS / hardware supports
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxCursorNameLength( ) //TODO, don't know
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxIndexLength( ) //TODO, don't know
+{
+ // LEM: that's the index itself, not its name
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxSchemaNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxProcedureNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxCatalogNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxRowSize( )
+{
+ // jdbc driver says 1GB, but http://www.postgresql.org/about/ says 1.6TB
+ // and that 1GB is the maximum _field_ size
+ // The row limit does not fit into a sal_Int32
+ return 0;
+}
+
+sal_Bool DatabaseMetaData::doesMaxRowSizeIncludeBlobs( )
+{
+ // LEM: Err... PostgreSQL basically does not do BLOBs well
+ // In any case, BLOBs do not change the maximal row length AFAIK
+ return true;
+}
+
+sal_Int32 DatabaseMetaData::getMaxStatementLength( )
+{
+ // LEM: actually, that would be 2^sizeof(size_t)-1
+ // on the server? on the client (because of libpq)? minimum of the two? not sure
+ // Anyway, big, so say unlimited.
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxStatements( ) //TODO, don't know
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxTableNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getMaxTablesInSelect( )
+{
+ return 0;
+}
+
+sal_Int32 DatabaseMetaData::getMaxUserNameLength( )
+{
+ return getMaxNameLength();
+}
+
+sal_Int32 DatabaseMetaData::getDefaultTransactionIsolation( )
+{
+ return css::sdbc::TransactionIsolation::READ_COMMITTED;
+}
+
+sal_Bool DatabaseMetaData::supportsTransactions( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 level )
+{
+ if ( level == css::sdbc::TransactionIsolation::READ_COMMITTED
+ || level == css::sdbc::TransactionIsolation::SERIALIZABLE
+ || level == css::sdbc::TransactionIsolation::READ_UNCOMMITTED
+ || level == css::sdbc::TransactionIsolation::REPEATABLE_READ)
+ return true;
+ else
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions( )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsDataManipulationTransactionsOnly( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::dataDefinitionCausesTransactionCommit( )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::dataDefinitionIgnoredInTransactions( )
+{
+ return false;
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getProcedures(
+ const css::uno::Any&,
+ const OUString&,
+ const OUString& )
+{
+// 1. PROCEDURE_CAT string =&gt; procedure catalog (may be NULL )
+// 2. PROCEDURE_SCHEM string =&gt; procedure schema (may be NULL )
+// 3. PROCEDURE_NAME string =&gt; procedure name
+// 4. reserved for future use
+// 5. reserved for future use
+// 6. reserved for future use
+// 7. REMARKS string =&gt; explanatory comment on the procedure
+// 8. PROCEDURE_TYPE short =&gt; kind of procedure:
+// * UNKNOWN - May return a result
+// * NO - Does not return a result
+// * RETURN - Returns a result
+
+// LEM TODO: implement
+// LEM TODO: at least fake the columns, even if no row.
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > > (), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getProcedureColumns(
+ const css::uno::Any&,
+ const OUString&,
+ const OUString&,
+ const OUString& )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+// LEM TODO: implement
+// LEM TODO: at least fake the columns, even if no row.
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getTables(
+ const css::uno::Any&,
+ const OUString& schemaPattern,
+ const OUString& tableNamePattern,
+ const css::uno::Sequence< OUString >& )
+{
+ Statics &statics = getStatics();
+
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTables() got called with " << schemaPattern << "." << tableNamePattern);
+
+ // ignore catalog, as a single pq connection does not support multiple catalogs
+
+ // LEM TODO: this does not give the right column names, not the right number of columns, etc.
+ // Take "inspiration" from JDBC driver
+ // Ah, this is used to create a XResultSet manually... Try to do it directly in SQL
+ Reference< XPreparedStatement > statement = m_origin->prepareStatement(
+ "SELECT "
+ "DISTINCT ON (pg_namespace.nspname, relname ) " // avoid duplicates (pg_settings !)
+ "pg_namespace.nspname, relname, relkind, pg_description.description "
+ "FROM pg_namespace, pg_class LEFT JOIN pg_description ON pg_class.oid = pg_description.objoid "
+ "WHERE relnamespace = pg_namespace.oid "
+ "AND ( relkind = 'r' OR relkind = 'v') "
+ "AND pg_namespace.nspname LIKE ? "
+ "AND relname LIKE ? "
+// "ORDER BY pg_namespace.nspname || relname"
+ );
+
+ Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
+ parameters->setString( 1 , schemaPattern );
+ parameters->setString( 2 , tableNamePattern );
+
+ Reference< XResultSet > rs = statement->executeQuery();
+ Reference< XRow > xRow( rs, UNO_QUERY_THROW );
+ std::vector< std::vector<Any> > vec;
+
+ while( rs->next() )
+ {
+ std::vector< Any > row( 5 );
+
+ row[0] <<= m_pSettings->catalog;
+ row[1] <<= xRow->getString( 1 );
+ row[2] <<= xRow->getString( 2 );
+ OUString type = xRow->getString(3);
+ if( type == "r" )
+ {
+ if( xRow->getString(1) == "pg_catalog" )
+ {
+ row[3] <<= statics.SYSTEM_TABLE;
+ }
+ else
+ {
+ row[3] <<= statics.TABLE;
+ }
+ }
+ else if( type == "v" )
+ {
+ row[3] <<= statics.VIEW;
+ }
+ else
+ {
+ row[3] <<= statics.UNKNOWN;
+ }
+ row[4] <<= xRow->getString(4);
+
+ // no description in postgresql AFAIK
+ vec.push_back( row );
+ }
+ Reference< XCloseable > closeable( statement, UNO_QUERY );
+ if( closeable.is() )
+ closeable->close();
+
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(statics.tablesRowNames), std::move(vec), m_pSettings->tc );
+}
+
+namespace
+{
+ // sort no schema first, then "public", then normal schemas, then internal schemas
+ int compare_schema(std::u16string_view nsA, std::u16string_view nsB)
+ {
+ if (nsA.empty())
+ {
+ return nsB.empty() ? 0 : -1;
+ }
+ else if (nsB.empty())
+ {
+ assert(!nsA.empty());
+ return 1;
+ }
+ else if(nsA == u"public")
+ {
+ return (nsB == u"public") ? 0 : -1;
+ }
+ else if(nsB == u"public")
+ {
+ assert(nsA != u"public");
+ return 1;
+ }
+ else if(o3tl::starts_with(nsA, u"pg_"))
+ {
+ if(o3tl::starts_with(nsB, u"pg_"))
+ return nsA.compare(nsB);
+ else
+ return 1;
+ }
+ else if(o3tl::starts_with(nsB, u"pg_"))
+ {
+ return -1;
+ }
+ else
+ {
+ return nsA.compare(nsB);
+ }
+ }
+
+ struct SortInternalSchemasLastAndPublicFirst
+ {
+ bool operator () ( const std::vector< Any > & a, const std::vector< Any > & b )
+ {
+ OUString valueA;
+ OUString valueB;
+ a[0] >>= valueA;
+ b[0] >>= valueB;
+ return compare_schema(valueA, valueB) < 0;
+ }
+ };
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getSchemas( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getSchemas() got called");
+
+ // <b>TABLE_SCHEM</b> string =&amp;gt; schema name
+ Reference< XStatement > statement = m_origin->createStatement();
+ Reference< XResultSet > rs = statement->executeQuery(
+ "SELECT nspname from pg_namespace" );
+ // LEM TODO: look at JDBC driver and consider doing the same
+ // in particular, excluding temporary schemas, but maybe better through pg_is_other_temp_schema(oid) OR == pg_my_temp_schema()
+
+ Reference< XRow > xRow( rs, UNO_QUERY_THROW );
+ std::vector< std::vector<Any> > vec;
+ while( rs->next() )
+ {
+ vec.push_back( { Any(xRow->getString(1)) } );
+ }
+
+ // sort public first, sort internal schemas last, sort rest in alphabetic order
+ std::sort( vec.begin(), vec.end(), SortInternalSchemasLastAndPublicFirst() );
+
+ Reference< XCloseable > closeable( statement, UNO_QUERY );
+ if( closeable.is() )
+ closeable->close();
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(getStatics().schemaNames), std::move(vec), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getCatalogs( )
+{
+ // LEM TODO: return the current catalog like JDBC driver?
+ // at least fake the columns, even if no content
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getTableTypes( )
+{
+ // LEM TODO: this can be made dynamic, see JDBC driver
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(getStatics().tableTypeNames), std::vector(getStatics().tableTypeData),
+ m_pSettings->tc );
+}
+
+
+/** returns the constant from sdbc.DataType
+ */
+sal_Int32 typeNameToDataType( const OUString &typeName, std::u16string_view typtype )
+{
+// sal_Int32 ret = css::sdbc::DataType::DISTINCT;
+ // map all unknown types to memo (longvarchar). This allows to show them in
+ // string representation. Additionally, the edit-table-type-selection-box
+ // is not so unusable anymore.
+ sal_Int32 ret = css::sdbc::DataType::LONGVARCHAR;
+ if( typtype == u"b" )
+ {
+ // as long as the OOo framework does not support arrays,
+ // the user is better of with interpreting arrays as strings !
+// if( typeName.getLength() && '_' == typeName[0] )
+// {
+// it's just a naming convention, but as long as we don't have anything better,
+// we take it as granted
+// ret = css::sdbc::DataType::ARRAY;
+// }
+ // base type
+ Statics &statics = getStatics();
+ BaseTypeMap::const_iterator ii = statics.baseTypeMap.find( typeName );
+ if( ii != statics.baseTypeMap.end() )
+ {
+ ret = ii->second;
+ }
+ }
+ else if( typtype == u"c" )
+ {
+ ret = css::sdbc::DataType::STRUCT;
+ }
+ else if( typtype == u"d" )
+ {
+ ret = css::sdbc::DataType::LONGVARCHAR;
+ }
+ return ret;
+}
+
+namespace {
+ bool isSystemColumn( sal_Int16 attnum )
+ {
+ return attnum <= 0;
+ }
+
+ // is not exported by the postgres header
+ const int PQ_VARHDRSZ = sizeof( sal_Int32 );
+
+ // Oh, quelle horreur
+ // LEM TODO: Need to severely rewrite that!
+ // should probably just "do the same" as ODBC or JDBC drivers...
+ void extractPrecisionAndScale(
+ sal_Int32 dataType, sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
+ {
+ if( atttypmod < PQ_VARHDRSZ )
+ {
+ *precision = 0;
+ *scale = 0;
+ }
+ else
+ {
+ switch( dataType )
+ {
+ case css::sdbc::DataType::NUMERIC:
+ case css::sdbc::DataType::DECIMAL:
+ {
+ *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
+ *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
+ break;
+ }
+ default:
+ *precision = atttypmod - PQ_VARHDRSZ;
+ *scale = 0;
+ }
+ }
+ }
+
+ struct DatabaseTypeDescription
+ {
+ DatabaseTypeDescription()
+ {}
+ DatabaseTypeDescription( const OUString &name, const OUString & type ) :
+ typeName( name ),
+ typeType( type )
+ {}
+ DatabaseTypeDescription( const DatabaseTypeDescription &source ) :
+ typeName( source.typeName ),
+ typeType( source.typeType )
+ {}
+ DatabaseTypeDescription & operator = ( const DatabaseTypeDescription & source )
+ {
+ typeName = source.typeName;
+ typeType = source.typeType;
+ return *this;
+ }
+ OUString typeName;
+ OUString typeType;
+ };
+}
+
+typedef std::unordered_map
+<
+ sal_Int32,
+ DatabaseTypeDescription
+> Oid2DatabaseTypeDescriptionMap;
+
+static void columnMetaData2DatabaseTypeDescription(
+ Oid2DatabaseTypeDescriptionMap &oidMap,
+ const Reference< XResultSet > &rs,
+ const Reference< XStatement > &stmt )
+{
+ Reference< XRow > row( rs, UNO_QUERY_THROW );
+ int domains = 0;
+ OUStringBuffer queryBuf(128);
+ queryBuf.append( "SELECT oid,typtype,typname FROM pg_TYPE WHERE " );
+ while( rs->next() )
+ {
+ if( row->getString( 9 ) == "d" && oidMap.find( row->getInt( 12 ) ) == oidMap.end() )
+ {
+ oidMap[row->getInt(12)] = DatabaseTypeDescription();
+ if( domains )
+ queryBuf.append( " OR " );
+ queryBuf.append( "oid = " );
+ queryBuf.append( row->getInt(12 ) );
+ domains ++;
+ }
+ }
+ rs->beforeFirst();
+
+ if( domains )
+ {
+ Reference< XResultSet > rsDomain = stmt->executeQuery( queryBuf.makeStringAndClear() );
+ row.set( rsDomain, UNO_QUERY_THROW );
+ while( rsDomain->next() )
+ {
+ oidMap[row->getInt(1)] = DatabaseTypeDescription(row->getString(3), row->getString(2) );
+ }
+ disposeNoThrow( stmt );
+ }
+
+}
+
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getColumns(
+ const css::uno::Any&,
+ const OUString& schemaPattern,
+ const OUString& tableNamePattern,
+ const OUString& columnNamePattern )
+{
+ // LEM TODO: review in comparison with JDBC driver
+ Statics &statics = getStatics();
+
+ // continue !
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getColumns() got called with "
+ << schemaPattern << "." << tableNamePattern << "." << columnNamePattern);
+
+ // ignore catalog, as a single pq connection
+ // does not support multiple catalogs anyway
+ // We don't use information_schema.columns because it contains
+ // only the columns the current user has any privilege over.
+
+ // 1. TABLE_CAT string => table catalog (may be NULL)
+ // => not supported
+ // 2. TABLE_SCHEM string => table schema (may be NULL)
+ // => pg_namespace.nspname
+ // 3. TABLE_NAME string => table name
+ // => pg_class.relname
+ // 4. COLUMN_NAME string => column name
+ // => pg_attribute.attname
+ // 5. DATA_TYPE short => SQL type from java.sql.Types
+ // => pg_type.typname => sdbc.DataType
+ // 6. TYPE_NAME string => Data source dependent type name, for a UDT the
+ // type name is fully qualified
+ // => pg_type.typname
+ // 7. COLUMN_SIZE long => column size. For char or date types this is
+ // the maximum number of characters, for numeric
+ // or decimal types this is precision.
+ // => pg_attribute.atttypmod
+ // 8. BUFFER_LENGTH is not used.
+ // => not used
+ // 9. DECIMAL_DIGITS long => the number of fractional digits
+ // => don't know ! TODO !
+ // 10. NUM_PREC_RADIX long => Radix (typically either 10 or 2)
+ // => TODO ??
+ // 11. NULLABLE long => is NULL allowed?
+ // NO_NULLS - might not allow NULL values
+ // NULABLE - definitely allows NULL values
+ // NULLABLE_UNKNOWN - nullability unknown
+ // => pg_attribute.attnotnull
+ // 12. REMARKS string => comment describing column (may be NULL )
+ // => pg_description.description
+ // 13. COLUMN_DEF string => default value (may be NULL)
+ // => pg_type.typdefault
+ // 14. SQL_DATA_TYPE long => unused
+ // => empty
+ // 15. SQL_DATETIME_SUB long => unused
+ // => empty
+ // 16. CHAR_OCTET_LENGTH long => for char types the maximum number of
+ // bytes in the column
+ // => pg_type.typlen
+ // 17. ORDINAL_POSITION int => index of column in table (starting at 1)
+ // pg_attribute.attnum
+ // 18. IS_NULLABLE string => "NO" means column definitely does not allow
+ // NULL values; "YES" means the column might
+ // allow NULL values. An empty string means
+ // nobody knows.
+ // => pg_attribute.attnotnull
+ OUString strDefaultValue = getColExprForDefaultSettingVal(m_pSettings);
+ Reference< XPreparedStatement > statement = m_origin->prepareStatement(
+ "SELECT pg_namespace.nspname, " // 1
+ "pg_class.relname, " // 2
+ "pg_attribute.attname, " // 3
+ "pg_type.typname, " // 4
+ "pg_attribute.atttypmod, " // 5
+ "pg_attribute.attnotnull, " // 6
+ "pg_type.typdefault, " // 7
+ "pg_type.typtype, " // 8
+ + strDefaultValue + // 9
+ ",pg_description.description, " // 10
+ "pg_type.typbasetype, " // 11
+ "pg_attribute.attnum " // 12
+ "FROM pg_class, "
+ "pg_attribute LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND pg_attribute.attnum = pg_attrdef.adnum "
+ "LEFT JOIN pg_description ON pg_attribute.attrelid = pg_description.objoid AND pg_attribute.attnum=pg_description.objsubid,"
+ " pg_type, pg_namespace "
+ "WHERE pg_attribute.attrelid = pg_class.oid "
+ "AND pg_attribute.atttypid = pg_type.oid "
+ "AND pg_class.relnamespace = pg_namespace.oid "
+ "AND NOT pg_attribute.attisdropped "
+ "AND pg_namespace.nspname LIKE ? "
+ "AND pg_class.relname LIKE ? "
+ "AND pg_attribute.attname LIKE ? "
+ "ORDER BY pg_namespace.nspname, pg_class.relname, pg_attribute.attnum"
+ );
+
+ Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
+ parameters->setString( 1 , schemaPattern );
+ parameters->setString( 2 , tableNamePattern );
+ parameters->setString( 3 , columnNamePattern );
+
+ Reference< XResultSet > rs = statement->executeQuery();
+ Reference< XRow > xRow( rs, UNO_QUERY_THROW );
+ std::vector< std::vector<Any> > vec;
+
+ Oid2DatabaseTypeDescriptionMap domainMap;
+ Reference< XStatement > domainTypeStmt = m_origin->createStatement();
+ columnMetaData2DatabaseTypeDescription( domainMap, rs, domainTypeStmt );
+
+ sal_uInt32 colNum(0);
+ OUString sSchema( "#invalid#" );
+ OUString sTable( "#invalid#" );
+
+ while( rs->next() )
+ {
+ if( ! isSystemColumn( xRow->getShort( 12 ) ) )
+ {
+ OUString sNewSchema( xRow->getString(1) );
+ OUString sNewTable( xRow->getString(2) );
+ if ( sNewSchema != sSchema || sNewTable != sTable )
+ {
+ colNum = 1;
+ sSchema = sNewSchema;
+ sTable = sNewTable;
+ }
+ else
+ ++colNum;
+ sal_Int32 precision, scale, type;
+ std::vector< Any > row( 18 );
+ row[0] <<= m_pSettings->catalog;
+ row[1] <<= sNewSchema;
+ row[2] <<= sNewTable;
+ row[3] <<= xRow->getString(3);
+ if( xRow->getString(8) == "d" )
+ {
+ DatabaseTypeDescription desc( domainMap[xRow->getInt(11)] );
+ type = typeNameToDataType( desc.typeName, desc.typeType );
+ }
+ else
+ {
+ type = typeNameToDataType( xRow->getString(4), xRow->getString(8) );
+ }
+ extractPrecisionAndScale( type, xRow->getInt(5) , &precision, &scale );
+ row[4] <<= type;
+ row[5] <<= xRow->getString(4);
+ row[6] <<= precision;
+ // row[7] BUFFER_LENGTH not used
+ row[8] <<= scale;
+ // row[9] RADIX TODO
+ if( xRow->getBoolean( 6 ) && ! isSystemColumn(xRow->getInt( 12 )) )
+ {
+ row[10] <<= OUString::number(css::sdbc::ColumnValue::NO_NULLS);
+ row[17] <<= statics.NO;
+ }
+ else
+ {
+ row[10] <<= OUString::number(css::sdbc::ColumnValue::NULLABLE);
+ row[17] <<= statics.YES;
+ }
+
+ row[11] <<= xRow->getString( 10 ); // comment
+ row[12] <<= xRow->getString( 9 ); // COLUMN_DEF = pg_type.typdefault
+ // row[13] SQL_DATA_TYPE not used
+ // row[14] SQL_DATETIME_SUB not used
+ row[15] <<= precision;
+ row[16] <<= colNum ;
+
+ vec.push_back( row );
+ }
+ }
+ Reference< XCloseable > closeable( statement, UNO_QUERY );
+ if( closeable.is() )
+ closeable->close();
+
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(statics.columnRowNames), std::move(vec), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getColumnPrivileges(
+ const css::uno::Any&,
+ const OUString& schema,
+ const OUString& table,
+ const OUString& columnNamePattern )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getColumnPrivileges() got called with "
+ << schema << "." << table << "." << columnNamePattern);
+
+ Reference< XParameters > parameters( m_getColumnPrivs_stmt, UNO_QUERY_THROW );
+ parameters->setString( 1 , schema );
+ parameters->setString( 2 , table );
+ parameters->setString( 3 , columnNamePattern );
+
+ Reference< XResultSet > rs = m_getColumnPrivs_stmt->executeQuery();
+
+ return rs;
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getTablePrivileges(
+ const css::uno::Any&,
+ const OUString& schemaPattern,
+ const OUString& tableNamePattern )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTablePrivileges() got called with "
+ << schemaPattern << "." << tableNamePattern);
+
+ Reference< XParameters > parameters( m_getTablePrivs_stmt, UNO_QUERY_THROW );
+ parameters->setString( 1 , schemaPattern );
+ parameters->setString( 2 , tableNamePattern );
+
+ Reference< XResultSet > rs = m_getTablePrivs_stmt->executeQuery();
+
+ return rs;
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getBestRowIdentifier(
+ const css::uno::Any&,
+ const OUString&,
+ const OUString&,
+ sal_Int32,
+ sal_Bool )
+{
+ //LEM TODO: implement! See JDBC driver
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getVersionColumns(
+ const css::uno::Any&,
+ const OUString&,
+ const OUString& )
+{
+ //LEM TODO: implement! See JDBC driver
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getPrimaryKeys(
+ const css::uno::Any&,
+ const OUString& schema,
+ const OUString& table )
+{
+ //LEM TODO: review
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+// 1. TABLE_CAT string =&gt; table catalog (may be NULL )
+// 2. TABLE_SCHEM string =&gt; table schema (may be NULL )
+// 3. TABLE_NAME string =&gt; table name
+// 4. COLUMN_NAME string =&gt; column name
+// 5. KEY_SEQ short =&gt; sequence number within primary key
+// 6. PK_NAME string =&gt; primary key name (may be NULL )
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getPrimaryKeys() got called with "
+ << schema << "." << table);
+
+ Reference< XPreparedStatement > statement = m_origin->prepareStatement(
+ "SELECT nmsp.nspname, "
+ "cl.relname, "
+ "con.conkey, "
+ "con.conname, "
+ "con.conrelid "
+ "FROM pg_constraint as con,pg_class as cl, pg_namespace as nmsp "
+ "WHERE con.connamespace = nmsp.oid AND con.conrelid = cl.oid AND con.contype = 'p' "
+ "AND nmsp.nspname LIKE ? AND cl.relname LIKE ?" );
+
+ Reference< XParameters > parameters( statement, UNO_QUERY_THROW );
+ parameters->setString( 1 , schema );
+ parameters->setString( 2 , table );
+
+ Reference< XResultSet > rs = statement->executeQuery();
+ Reference< XRow > xRow( rs, UNO_QUERY_THROW );
+ std::vector< std::vector<Any> > vec;
+
+ while( rs->next() )
+ {
+ std::vector< Any > row( 6 );
+ row[0] <<= m_pSettings->catalog;
+ row[1] <<= xRow->getString(1);
+ row[2] <<= xRow->getString(2);
+ OUString array = xRow->getString(3);
+ row[4] <<= xRow->getString(5); // the relid
+ row[5] <<= xRow->getString(4);
+
+ int i = 0;
+ // now retrieve the columns information
+ // unfortunately, postgresql does not allow array of variable size in
+ // WHERE clauses (in the default installation), so we have to choose
+ // this expensive and somewhat ugly way
+ // annotation: postgresql shouldn't have chosen an array here, instead they
+ // should have multiple rows per table
+ // LEM: to transform an array into several rows, see unnest;
+ // it is as simple as "SELECT foo, bar, unnest(qux) FROM ..."
+ // where qux is the column that contains an array.
+ while( array[i] && '}' != array[i] )
+ {
+ i++;
+ int start = i;
+ while( array[i] && array[i] != '}' && array[i] != ',' ) i++;
+ row[3] <<= array.copy(start, i - start );
+ vec.push_back( row );
+ }
+ }
+
+ {
+ Reference< XCloseable > closeable( statement, UNO_QUERY );
+ if( closeable.is() )
+ closeable->close();
+ }
+
+
+ OUString lastTableOid;
+ sal_Int32 index = 0;
+ std::vector< std::vector< Any > > ret( vec.size() );
+ int elements = 0;
+ for (auto const& elem : vec)
+ {
+
+ std::vector< Any > row = elem;
+ OUString tableOid;
+ OUString attnum;
+
+ row[4] >>= tableOid;
+ row[3] >>= attnum;
+ statement = m_origin->prepareStatement(
+ "SELECT att.attname FROM "
+ "pg_attribute AS att, pg_class AS cl WHERE "
+ "att.attrelid = ? AND att.attnum = ?" );
+
+ parameters.set( statement, UNO_QUERY_THROW );
+ parameters->setString( 1 , tableOid );
+ parameters->setString( 2 , attnum );
+
+ rs = statement->executeQuery();
+ xRow.set( rs, UNO_QUERY_THROW );
+ if( rs->next() )
+ {
+ // column name
+ row[3] <<= xRow->getString( 1 );
+ if( tableOid != lastTableOid )
+ index = 1;
+ lastTableOid = tableOid;
+ row[4] <<= OUString::number( index );
+ index ++;
+ }
+ {
+ Reference< XCloseable > closeable( statement, UNO_QUERY );
+ if( closeable.is() )
+ closeable->close();
+ }
+ ret[elements] = row;
+ elements ++;
+ }
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(getStatics().primaryKeyNames), std::move(ret), m_pSettings->tc );
+}
+
+// Copied / adapted / simplified from JDBC driver
+#define SQL_CASE_KEYRULE " WHEN 'c' THEN " SAL_STRINGIFY(KEYRULE_CASCADE) \
+ " WHEN 'n' THEN " SAL_STRINGIFY(KEYRULE_SET_NULL) \
+ " WHEN 'd' THEN " SAL_STRINGIFY(KEYRULE_SET_DEFAULT) \
+ " WHEN 'r' THEN " SAL_STRINGIFY(KEYRULE_RESTRICT) \
+ " WHEN 'a' THEN " SAL_STRINGIFY(KEYRULE_NO_ACTION) \
+ " ELSE NULL "
+
+#define SQL_GET_REFERENCES \
+ "WITH con AS (SELECT oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, generate_subscripts(conkey,1) AS conkeyseq, unnest(conkey) AS conkey , unnest(confkey) AS confkey FROM pg_catalog.pg_constraint) " \
+ "SELECT NULL::text AS PKTABLE_CAT, pkn.nspname AS PKTABLE_SCHEM, pkc.relname AS PKTABLE_NAME, pka.attname AS PKCOLUMN_NAME, " \
+ " NULL::text AS FKTABLE_CAT, fkn.nspname AS FKTABLE_SCHEM, fkc.relname AS FKTABLE_NAME, fka.attname AS FKCOLUMN_NAME, " \
+ " con.conkeyseq AS KEY_SEQ, " \
+ " CASE con.confupdtype " \
+ SQL_CASE_KEYRULE \
+ " END AS UPDATE_RULE, " \
+ " CASE con.confdeltype " \
+ SQL_CASE_KEYRULE \
+ " END AS DELETE_RULE, " \
+ " con.conname AS FK_NAME, pkic.relname AS PK_NAME, " \
+ " CASE " \
+ " WHEN con.condeferrable AND con.condeferred THEN " SAL_STRINGIFY(DEFERRABILITY_INITIALLY_DEFERRED) \
+ " WHEN con.condeferrable THEN " SAL_STRINGIFY(DEFERRABILITY_INITIALLY_IMMEDIATE) \
+ " ELSE " SAL_STRINGIFY(DEFERRABILITY_NONE) \
+ " END AS DEFERRABILITY " \
+ "FROM " \
+ " pg_catalog.pg_namespace pkn, pg_catalog.pg_class pkc, pg_catalog.pg_attribute pka, " \
+ " pg_catalog.pg_namespace fkn, pg_catalog.pg_class fkc, pg_catalog.pg_attribute fka, " \
+ " con, pg_catalog.pg_depend dep, pg_catalog.pg_class pkic " \
+ "WHERE pkn.oid = pkc.relnamespace AND pkc.oid = pka.attrelid AND pka.attnum = con.confkey AND con.confrelid = pkc.oid " \
+ " AND fkn.oid = fkc.relnamespace AND fkc.oid = fka.attrelid AND fka.attnum = con.conkey AND con.conrelid = fkc.oid " \
+ " AND con.contype = 'f' AND con.oid = dep.objid AND pkic.oid = dep.refobjid AND pkic.relkind = 'i' AND dep.classid = 'pg_constraint'::regclass::oid AND dep.refclassid = 'pg_class'::regclass::oid "
+
+#define SQL_GET_REFERENCES_PSCHEMA " AND pkn.nspname = ? "
+#define SQL_GET_REFERENCES_PTABLE " AND pkc.relname = ? "
+#define SQL_GET_REFERENCES_FSCHEMA " AND fkn.nspname = ? "
+#define SQL_GET_REFERENCES_FTABLE " AND fkc.relname = ? "
+#define SQL_GET_REFERENCES_ORDER_SOME_PTABLE "ORDER BY fkn.nspname, fkc.relname, conkeyseq"
+#define SQL_GET_REFERENCES_ORDER_NO_PTABLE "ORDER BY pkn.nspname, pkc.relname, conkeyseq"
+
+#define SQL_GET_REFERENCES_NONE_NONE_NONE_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_NONE_NONE_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_SOME_NONE_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_SOME_NONE_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_NONE_SOME_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_NONE_NONE_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_NONE_SOME_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_NONE_SOME_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_NONE_NONE_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_NONE_SOME_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_NO_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_SOME_SOME_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_SOME_NONE_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_NONE_SOME_SOME_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_SOME_SOME_NONE \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_SOME_NONE_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+#define SQL_GET_REFERENCES_SOME_SOME_SOME_SOME \
+ SQL_GET_REFERENCES \
+ SQL_GET_REFERENCES_PSCHEMA \
+ SQL_GET_REFERENCES_PTABLE \
+ SQL_GET_REFERENCES_FSCHEMA \
+ SQL_GET_REFERENCES_FTABLE \
+ SQL_GET_REFERENCES_ORDER_SOME_PTABLE
+
+void DatabaseMetaData::init_getReferences_stmt ()
+{
+ m_getReferences_stmt[0] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_NONE_NONE_NONE);
+ m_getReferences_stmt[1] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_NONE_NONE_NONE);
+ m_getReferences_stmt[2] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_SOME_NONE_NONE);
+ m_getReferences_stmt[3] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_SOME_NONE_NONE);
+ m_getReferences_stmt[4] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_NONE_SOME_NONE);
+ m_getReferences_stmt[5] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_NONE_SOME_NONE);
+ m_getReferences_stmt[6] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_SOME_SOME_NONE);
+ m_getReferences_stmt[7] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_SOME_SOME_NONE);
+ m_getReferences_stmt[8] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_NONE_NONE_SOME);
+ m_getReferences_stmt[9] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_NONE_NONE_SOME);
+ m_getReferences_stmt[10] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_SOME_NONE_SOME);
+ m_getReferences_stmt[11] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_SOME_NONE_SOME);
+ m_getReferences_stmt[12] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_NONE_SOME_SOME);
+ m_getReferences_stmt[13] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_NONE_SOME_SOME);
+ m_getReferences_stmt[14] = m_origin->prepareStatement(SQL_GET_REFERENCES_NONE_SOME_SOME_SOME);
+ m_getReferences_stmt[15] = m_origin->prepareStatement(SQL_GET_REFERENCES_SOME_SOME_SOME_SOME);
+}
+
+void DatabaseMetaData::init_getPrivs_stmt ()
+{
+ OUStringBuffer sSQL(300);
+ sSQL.append(
+ " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.privilege, dp.is_grantable "
+ " FROM ("
+ " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name,"
+ " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
+ " FROM information_schema.table_privileges");
+ if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
+ // information_schema.table_privileges does not fill in default ACLs when no ACL
+ // assume default ACL is "owner has all privileges" and add it
+ sSQL.append(
+ " UNION "
+ " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME,"
+ " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
+ " FROM pg_catalog.pg_class c,"
+ " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) p (privilege),"
+ " pg_catalog.pg_roles ro,"
+ " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
+ " UNION ALL"
+ " VALUES (0::oid, 'PUBLIC')"
+ " ) AS rg (oid, rolname),"
+ " pg_catalog.pg_namespace pn"
+ " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
+ " AND c.relowner=ro.oid AND c.relnamespace = pn.oid");
+ sSQL.append(
+ " ) dp,"
+ " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
+ " WHERE table_schem LIKE ? AND table_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
+ " ORDER BY table_schem, table_name, privilege" );
+
+ m_getTablePrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
+
+ sSQL.append(
+ " SELECT dp.TABLE_CAT, dp.TABLE_SCHEM, dp.TABLE_NAME, dp.COLUMN_NAME, dp.GRANTOR, pr.rolname AS GRANTEE, dp.PRIVILEGE, dp.IS_GRANTABLE FROM ("
+ " SELECT table_catalog AS TABLE_CAT, table_schema AS TABLE_SCHEM, table_name, column_name,"
+ " grantor, grantee, privilege_type AS PRIVILEGE, is_grantable"
+ " FROM information_schema.column_privileges");
+ if ( PQserverVersion( m_pSettings->pConnection ) < 90200 )
+ // information_schema.table_privileges does not fill in default ACLs when no ACL
+ // assume default ACL is "owner has all privileges" and add it
+ sSQL.append(
+ " UNION "
+ " SELECT current_database() AS TABLE_CAT, pn.nspname AS TABLE_SCHEM, c.relname AS TABLE_NAME, a.attname AS column_name,"
+ " ro.rolname AS GRANTOR, rg.rolname AS GRANTEE, p.privilege, 'YES' AS is_grantable"
+ " FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a,"
+ " (VALUES ('SELECT'), ('INSERT'), ('UPDATE'), ('REFERENCES')) p (privilege),"
+ " pg_catalog.pg_roles ro,"
+ " ( SELECT oid, rolname FROM pg_catalog.pg_roles"
+ " UNION ALL"
+ " VALUES (0::oid, 'PUBLIC')"
+ " ) AS rg (oid, rolname),"
+ " pg_catalog.pg_namespace pn"
+ " WHERE c.relkind IN ('r', 'v') AND c.relacl IS NULL AND pg_has_role(rg.oid, c.relowner, 'USAGE')"
+ " AND c.relowner=ro.oid AND c.relnamespace = pn.oid AND a.attrelid = c.oid AND a.attnum > 0");
+ sSQL.append(
+ " ) dp,"
+ " (SELECT oid, rolname FROM pg_catalog.pg_roles UNION ALL VALUES (0, 'PUBLIC')) pr"
+ " WHERE table_schem = ? AND table_name = ? AND column_name LIKE ? AND (dp.grantee = 'PUBLIC' OR pg_has_role(pr.oid, dp.grantee, 'USAGE'))"
+ " ORDER BY column_name, privilege" );
+
+ m_getColumnPrivs_stmt = m_origin->prepareStatement( sSQL.makeStringAndClear() );
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getImportedExportedKeys(
+ const Any& /* primaryCatalog */,
+ const OUString& primarySchema,
+ const OUString& primaryTable,
+ const Any& /* foreignCatalog */,
+ const OUString& foreignSchema,
+ const OUString& foreignTable )
+{
+ unsigned int i = 0;
+ if ( ! primarySchema.isEmpty() )
+ i |= 0x01;
+ if ( ! primaryTable.isEmpty() )
+ i |= 0x02;
+ if ( ! foreignSchema.isEmpty() )
+ i |= 0x04;
+ if ( ! foreignTable.isEmpty() )
+ i |= 0x08;
+
+ Reference< XPreparedStatement > stmt = m_getReferences_stmt[i];
+ Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
+
+ unsigned int j = 1;
+ if ( i & 0x01 )
+ param->setString( j++, primarySchema );
+ if ( i & 0x02 )
+ param->setString( j++, primaryTable );
+ if ( i & 0x04 )
+ param->setString( j++, foreignSchema );
+ if ( i & 0x08 )
+ param->setString( j++, foreignTable );
+
+ Reference< XResultSet > rs = stmt->executeQuery();
+
+ return rs;
+}
+
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getImportedKeys(
+ const css::uno::Any& catalog,
+ const OUString& schema,
+ const OUString& table )
+{
+ return getImportedExportedKeys(Any(), OUString(), OUString(), catalog, schema, table);
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getExportedKeys(
+ const css::uno::Any& catalog,
+ const OUString& schema,
+ const OUString& table )
+{
+ return getImportedExportedKeys(catalog, schema, table, Any(), OUString(), OUString());
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getCrossReference(
+ const css::uno::Any& primaryCatalog,
+ const OUString& primarySchema,
+ const OUString& primaryTable,
+ const css::uno::Any& foreignCatalog,
+ const OUString& foreignSchema,
+ const OUString& foreignTable )
+{
+ return getImportedExportedKeys( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable );
+}
+
+namespace
+{
+ struct TypeInfoByDataTypeSorter
+ {
+ bool operator () ( const std::vector< Any > & a, const std::vector< Any > & b )
+ {
+ OUString valueA;
+ OUString valueB;
+ a[1 /*DATA_TYPE*/] >>= valueA;
+ b[1 /*DATA_TYPE*/] >>= valueB;
+ if( valueB.toInt32() == valueA.toInt32() )
+ {
+ OUString nameA;
+ OUString nameB;
+ a[0 /*TYPE_NAME*/] >>= nameA;
+ b[0 /*TYPE_NAME*/] >>= nameB;
+ std::u16string_view nsA, tnA, nsB, tnB;
+
+ // parse typename into schema and typename
+ sal_Int32 nIndex=0;
+ nsA = o3tl::getToken(nameA, 0, '.', nIndex);
+ if (nIndex<0)
+ {
+ tnA = nsA;
+ nsA = std::u16string_view();
+ }
+ else
+ {
+ tnA = o3tl::getToken(nameA, 0, '.', nIndex);
+ assert(nIndex < 0);
+ }
+
+ nIndex=0;
+ nsB = o3tl::getToken(nameB, 0, '.', nIndex);
+ if (nIndex<0)
+ {
+ tnB = nsB;
+ nsB = std::u16string_view();
+ }
+ else
+ {
+ tnB = o3tl::getToken(nameB, 0, '.', nIndex);
+ assert(nIndex < 0);
+ }
+
+ const int ns_comp = compare_schema(nsA, nsB);
+ if(ns_comp == 0)
+ {
+ if(nsA.empty())
+ {
+ assert(nsB.empty());
+ // within each type category, sort privileged choice first
+ if( tnA == u"int4" || tnA == u"varchar" || tnA == u"char" || tnA == u"text")
+ return true;
+ if( tnB == u"int4" || tnB == u"varchar" || tnB == u"char" || tnB == u"text")
+ return false;
+ }
+ return nameA.compareTo( nameB ) < 0;
+ }
+ else
+ {
+ return ns_comp < 0;
+ }
+ }
+
+ return valueA.toInt32() < valueB.toInt32();
+ }
+ };
+
+ sal_Int32 calcSearchable( sal_Int32 dataType )
+ {
+ sal_Int32 ret = css::sdbc::ColumnSearch::FULL;
+ if( css::sdbc::DataType::BINARY == dataType ||
+ css::sdbc::DataType::VARBINARY == dataType ||
+ css::sdbc::DataType::LONGVARBINARY == dataType )
+ ret = css::sdbc::ColumnSearch::NONE;
+
+ return ret;
+ }
+
+ sal_Int32 getMaxScale( sal_Int32 dataType )
+ {
+ // LEM TODO: review, see where used, see JDBC, ...
+ sal_Int32 ret = 0;
+ if( dataType == css::sdbc::DataType::NUMERIC )
+ ret = 1000; // see pg-docs DataType/numeric
+// else if( dataType == DataType::DOUBLE )
+// ret = 308;
+// else if( dataType == DataType::FLOAT )
+// ret =
+ return ret;
+ }
+
+ OUString construct_full_typename(std::u16string_view ns, const OUString &tn)
+ {
+ if(ns.empty() || ns == u"pg_catalog")
+ return tn;
+ else
+ return OUString::Concat(ns) + "." + tn;
+ }
+
+ void pgTypeInfo2ResultSet(
+ std::vector< std::vector<Any> > &vec,
+ const Reference< XResultSet > &rs )
+ {
+ static const sal_Int32 TYPE_NAME = 0; // string Type name
+ static const sal_Int32 DATA_TYPE = 1; // short SQL data type from java.sql.Types
+ static const sal_Int32 PRECISION = 2; // long maximum precision
+ static const sal_Int32 CREATE_PARAMS = 5; // string => parameters used in creating the type (may be NULL )
+ static const sal_Int32 NULLABLE = 6; // short ==> can you use NULL for this type?
+ // - NO_NULLS - does not allow NULL values
+ // - NULLABLE - allows NULL values
+ // - NULLABLE_UNKNOWN - nullability unknown
+
+ static const sal_Int32 CASE_SENSITIVE = 7; // boolean==> is it case sensitive
+ static const sal_Int32 SEARCHABLE = 8; // short ==>; can you use
+ // "WHERE" based on this type:
+ // - NONE - No support
+ // - CHAR - Only supported with WHERE .. LIKE
+ // - BASIC - Supported except for WHERE .. LIKE
+ // - FULL - Supported for all WHERE ..
+ static const sal_Int32 UNSIGNED_ATTRIBUTE = 9; // boolean ==> is it unsigned?
+ // FIXED_PREC_SCALE = 10; boolean ==> can it be a money value?
+ static const sal_Int32 AUTO_INCREMENT = 11; // boolean ==> can it be used for
+ // an auto-increment value?
+ static const sal_Int32 MINIMUM_SCALE = 13; // short ==> minimum scale supported
+ static const sal_Int32 MAXIMUM_SCALE = 14; // short ==> maximum scale supported
+ static const sal_Int32 NUM_PREC_RADIX = 17; // long ==> usually 2 or 10
+
+ /* not filled so far
+ 3. LITERAL_PREFIX string ==> prefix used to quote a literal
+ (may be <NULL/>)
+ 4. LITERAL_SUFFIX string ==> suffix used to quote a literal
+ (may be <NULL/>)
+ 5. CREATE_PARAMS string ==> parameters used in creating the type (may be <NULL/>)
+ 12. LOCAL_TYPE_NAME string ==> localized version of type name (may be <NULL/>)
+ 15, SQL_DATA_TYPE long ==> unused
+ 16. SQL_DATETIME_SUB long ==> unused
+ */
+ Reference< XRow > xRow( rs, UNO_QUERY_THROW );
+ while( rs->next() )
+ {
+ std::vector< Any > row(18);
+
+ sal_Int32 dataType =typeNameToDataType(xRow->getString(5),xRow->getString(2));
+ sal_Int32 precision = xRow->getString(3).toInt32();
+
+ if( dataType == css::sdbc::DataType::CHAR ||
+ ( dataType == css::sdbc::DataType::VARCHAR &&
+ xRow->getString(TYPE_NAME+1).equalsIgnoreAsciiCase("varchar") ) )
+ {
+ // reflect varchar as varchar with upper limit !
+ //NOTE: the sql spec requires varchar to have an upper limit, however
+ // in postgresql the upper limit is optional, no limit means unlimited
+ // length (=1GB).
+ precision = 0x40000000; // about 1 GB, see character type docs in postgresql
+ row[CREATE_PARAMS] <<= OUString("length");
+ }
+ else if( dataType == css::sdbc::DataType::NUMERIC )
+ {
+ precision = 1000;
+ row[CREATE_PARAMS] <<= OUString("length, scale");
+ }
+
+ row[TYPE_NAME] <<= construct_full_typename(xRow->getString(6), xRow->getString(1));
+ row[DATA_TYPE] <<= OUString::number(dataType);
+ row[PRECISION] <<= OUString::number( precision );
+ sal_Int32 nullable = xRow->getBoolean(4) ?
+ css::sdbc::ColumnValue::NO_NULLS :
+ css::sdbc::ColumnValue::NULLABLE;
+ row[NULLABLE] <<= OUString::number(nullable);
+ row[CASE_SENSITIVE] <<= OUString::number(1);
+ row[SEARCHABLE] <<= OUString::number( calcSearchable( dataType ) );
+ row[UNSIGNED_ATTRIBUTE] <<= OUString("0");
+ if( css::sdbc::DataType::INTEGER == dataType ||
+ css::sdbc::DataType::BIGINT == dataType )
+ row[AUTO_INCREMENT] <<= OUString("1"); // TODO
+ else
+ row[AUTO_INCREMENT] <<= OUString("0"); // TODO
+ row[MINIMUM_SCALE] <<= OUString("0"); // TODO: what is this ?
+ row[MAXIMUM_SCALE] <<= OUString::number( getMaxScale( dataType ) );
+ row[NUM_PREC_RADIX] <<= OUString("10"); // TODO: what is this ?
+ vec.push_back( row );
+ }
+ }
+}
+
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getTypeInfo( )
+{
+ // Note: Indexes start at 0 (in the API doc, they start at 1)
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ SAL_INFO("connectivity.postgresql", "DatabaseMetaData::getTypeInfo() got called");
+
+ Reference< XStatement > statement = m_origin->createStatement();
+ Reference< XResultSet > rs = statement->executeQuery(
+ "SELECT pg_type.typname AS typname," //1
+ "pg_type.typtype AS typtype," //2
+ "pg_type.typlen AS typlen," //3
+ "pg_type.typnotnull AS typnotnull," //4
+ "pg_type.typname AS typname, " //5
+ "pg_namespace.nspname as typns " //6
+ "FROM pg_type LEFT JOIN pg_namespace ON pg_type.typnamespace=pg_namespace.oid "
+ "WHERE pg_type.typtype = 'b' "
+ "OR pg_type.typtype = 'p'"
+ );
+
+ std::vector< std::vector<Any> > vec;
+ pgTypeInfo2ResultSet( vec, rs );
+
+ // check for domain types
+ rs = statement->executeQuery(
+ "SELECT t1.typname as typname,"
+ "t2.typtype AS typtype,"
+ "t2.typlen AS typlen,"
+ "t2.typnotnull AS typnotnull,"
+ "t2.typname as realtypname, "
+ "pg_namespace.nspname as typns "
+ "FROM pg_type as t1 LEFT JOIN pg_type AS t2 ON t1.typbasetype=t2.oid LEFT JOIN pg_namespace ON t1.typnamespace=pg_namespace.oid "
+ "WHERE t1.typtype = 'd'" );
+ pgTypeInfo2ResultSet( vec, rs );
+
+ std::sort( vec.begin(), vec.end(), TypeInfoByDataTypeSorter() );
+
+ return new SequenceResultSet(
+ m_xMutex,
+ *this,
+ std::vector(getStatics().typeinfoColumnNames),
+ std::move(vec),
+ m_pSettings->tc,
+ &( getStatics().typeInfoMetaData ));
+}
+
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getIndexInfo(
+ const css::uno::Any& ,
+ const OUString& schema,
+ const OUString& table,
+ sal_Bool unique,
+ sal_Bool )
+{
+ //LEM TODO: review
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ /*
+ 1. TABLE_CAT string -> table catalog (may be NULL )
+ 2. TABLE_SCHEM string -> table schema (may be NULL )
+ 3. TABLE_NAME string -> table name
+ 4. NON_UNIQUE boolean -> Can index values be non-unique?
+ false when TYPE is tableIndexStatistic
+ 5. INDEX_QUALIFIER string -> index catalog (may be NULL );
+ NULL when TYPE is tableIndexStatistic
+ 6. INDEX_NAME string -> index name; NULL when TYPE is tableIndexStatistic
+ 7. TYPE short -> index type:
+ * 0 - this identifies table statistics that are returned
+ in conjunction with a table's index descriptions
+ * CLUSTERED - this is a clustered index
+ * HASHED - this is a hashed index
+ * OTHER - this is some other style of index
+ 8. ORDINAL_POSITION short -> column sequence number within index;
+ zero when TYPE is tableIndexStatistic
+ 9. COLUMN_NAME string -> column name; NULL when TYPE is tableIndexStatistic
+ 10. ASC_OR_DESC string -> column sort sequence, "A"= ascending,
+ "D" = descending, may be NULL if sort sequence
+ is not supported; NULL when TYPE is tableIndexStatistic
+ 11. CARDINALITY long -> When TYPE is tableIndexStatistic, then this is
+ the number of rows in the table; otherwise, it
+ is the number of unique values in the index.
+ 12. PAGES long -> When TYPE is tableIndexStatistic then this is
+ the number of pages used for the table, otherwise
+ it is the number of pages used for the current index.
+ 13. FILTER_CONDITION string -> Filter condition, if any. (may be NULL )
+
+ */
+ static const sal_Int32 C_SCHEMA = 1;
+ static const sal_Int32 C_TABLENAME = 2;
+ static const sal_Int32 C_INDEXNAME = 3;
+ static const sal_Int32 C_IS_CLUSTERED = 4;
+ static const sal_Int32 C_IS_UNIQUE = 5;
+ // C_IS_PRIMARY = 6
+ static const sal_Int32 C_COLUMNS = 7;
+
+ static const sal_Int32 R_TABLE_SCHEM = 1;
+ static const sal_Int32 R_TABLE_NAME = 2;
+ static const sal_Int32 R_NON_UNIQUE = 3;
+ static const sal_Int32 R_INDEX_NAME = 5;
+ static const sal_Int32 R_TYPE = 6;
+ static const sal_Int32 R_ORDINAL_POSITION = 7;
+ static const sal_Int32 R_COLUMN_NAME = 8;
+
+ Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
+ "SELECT nspname, " // 1
+ "pg_class.relname, " // 2
+ "class2.relname, " // 3
+ "indisclustered, " // 4
+ "indisunique, " // 5
+ "indisprimary, " // 6
+ "indkey " // 7
+ "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
+ "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
+ "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
+ "WHERE nspname = ? AND pg_class.relname = ?" );
+
+ Reference< XParameters > param ( stmt, UNO_QUERY_THROW );
+ param->setString( 1, schema );
+ param->setString( 2, table );
+ Reference< XResultSet > rs = stmt->executeQuery();
+ Reference< XRow > xRow ( rs, UNO_QUERY_THROW );
+
+ std::vector< std::vector<Any> > vec;
+ while( rs->next() )
+ {
+ std::vector< sal_Int32 > columns = parseIntArray( xRow->getString(C_COLUMNS) );
+ Reference< XPreparedStatement > columnsStmt = m_origin->prepareStatement(
+ "SELECT attnum, attname "
+ "FROM pg_attribute "
+ " INNER JOIN pg_class ON attrelid = pg_class.oid "
+ " INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid "
+ " WHERE pg_namespace.nspname=? AND pg_class.relname=?" );
+ Reference< XParameters > paramColumn ( columnsStmt, UNO_QUERY_THROW );
+ OUString currentSchema = xRow->getString( C_SCHEMA );
+ OUString currentTable = xRow->getString( C_TABLENAME );
+ OUString currentIndexName = xRow->getString( C_INDEXNAME );
+ bool isNonUnique = ! xRow->getBoolean( C_IS_UNIQUE );
+ sal_Int32 indexType = xRow->getBoolean( C_IS_CLUSTERED ) ?
+ css::sdbc::IndexType::CLUSTERED :
+ css::sdbc::IndexType::HASHED;
+
+ paramColumn->setString( C_SCHEMA, currentSchema );
+ paramColumn->setString( C_TABLENAME, currentTable );
+
+ Reference< XResultSet > rsColumn = columnsStmt->executeQuery();
+ Reference< XRow > rowColumn( rsColumn, UNO_QUERY_THROW );
+ while( rsColumn->next() )
+ {
+ auto findIt = std::find( columns.begin(), columns.end(), rowColumn->getInt( 1 ) );
+ if( findIt != columns.end() && ( ! isNonUnique || ! unique ) )
+ {
+ std::vector< Any > result( 13 );
+ result[R_TABLE_SCHEM] <<= currentSchema;
+ result[R_TABLE_NAME] <<= currentTable;
+ result[R_INDEX_NAME] <<= currentIndexName;
+ result[R_NON_UNIQUE] <<= isNonUnique;
+ result[R_TYPE] <<= indexType;
+ result[R_COLUMN_NAME] <<= rowColumn->getString(2);
+ sal_Int32 nPos = static_cast<sal_Int32>(findIt - columns.begin() +1); // MSVC++ nonsense
+ result[R_ORDINAL_POSITION] <<= nPos;
+ vec.push_back( result );
+ }
+ }
+ }
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector(getStatics().indexinfoColumnNames),
+ std::move(vec),
+ m_pSettings->tc );
+}
+
+sal_Bool DatabaseMetaData::supportsResultSetType( sal_Int32 setType )
+{
+ if ( setType == css::sdbc::ResultSetType::SCROLL_SENSITIVE )
+ return false;
+ else
+ return true;
+}
+
+sal_Bool DatabaseMetaData::supportsResultSetConcurrency(
+ sal_Int32 setType, sal_Int32 )
+{
+ if ( ! supportsResultSetType( setType ) )
+ return false;
+ else
+ return true;
+}
+
+sal_Bool DatabaseMetaData::ownUpdatesAreVisible( sal_Int32 /* setType */ )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::ownDeletesAreVisible( sal_Int32 /* setType */ )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::ownInsertsAreVisible( sal_Int32 /* setType */ )
+{
+ return true;
+}
+
+sal_Bool DatabaseMetaData::othersUpdatesAreVisible( sal_Int32 /* setType */ )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::othersDeletesAreVisible( sal_Int32 /* setType */ )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::othersInsertsAreVisible( sal_Int32 /* setType */ )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::updatesAreDetected( sal_Int32 /* setType */ )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::deletesAreDetected( sal_Int32 /* setType */ )
+{
+ return false;
+}
+sal_Bool DatabaseMetaData::insertsAreDetected( sal_Int32 /* setType */ )
+{
+ return false;
+}
+
+sal_Bool DatabaseMetaData::supportsBatchUpdates( )
+{
+ return true;
+}
+
+css::uno::Reference< XResultSet > DatabaseMetaData::getUDTs( const css::uno::Any&, const OUString&, const OUString&, const css::uno::Sequence< sal_Int32 >& )
+{
+ //LEM TODO: implement! See JDBC driver
+ MutexGuard guard( m_xMutex->GetMutex() );
+ return new SequenceResultSet(
+ m_xMutex, *this, std::vector< OUString >(), std::vector< std::vector< Any > >(), m_pSettings->tc );
+}
+
+css::uno::Reference< css::sdbc::XConnection > DatabaseMetaData::getConnection()
+{
+ return m_origin;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_databasemetadata.hxx b/connectivity/source/drivers/postgresql/pq_databasemetadata.hxx
new file mode 100644
index 000000000..134f72cf0
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_databasemetadata.hxx
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_connection.hxx"
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace pq_sdbc_driver
+{
+
+class DatabaseMetaData :
+ public ::cppu::WeakImplHelper< css::sdbc::XDatabaseMetaData >
+{
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ ConnectionSettings *m_pSettings;
+ css::uno::Reference< css::sdbc::XConnection > m_origin;
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_getIntSetting_stmt;
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_getReferences_stmt[16];
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_getTablePrivs_stmt;
+ css::uno::Reference< css::sdbc::XPreparedStatement > m_getColumnPrivs_stmt;
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ sal_Int32 getIntSetting(const OUString& settingName);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ sal_Int32 getMaxIndexKeys();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ sal_Int32 getMaxNameLength();
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ css::uno::Reference< css::sdbc::XResultSet > getImportedExportedKeys(
+ const css::uno::Any& primaryCatalog, const OUString& primarySchema, const OUString& primaryTable,
+ const css::uno::Any& foreignCatalog, const OUString& foreignSchema, const OUString& foreignTable );
+ void init_getReferences_stmt ();
+ void init_getPrivs_stmt ();
+
+public:
+ DatabaseMetaData(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & reMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings
+ );
+
+public:
+ // Methods
+ virtual sal_Bool SAL_CALL allProceduresAreCallable( ) override;
+ virtual sal_Bool SAL_CALL allTablesAreSelectable( ) override;
+ virtual OUString SAL_CALL getURL( ) override;
+ virtual OUString SAL_CALL getUserName( ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedHigh( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedLow( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedAtStart( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedAtEnd( ) override;
+ virtual OUString SAL_CALL getDatabaseProductName( ) override;
+ virtual OUString SAL_CALL getDatabaseProductVersion( ) override;
+ virtual OUString SAL_CALL getDriverName( ) override;
+ virtual OUString SAL_CALL getDriverVersion( ) override;
+ virtual sal_Int32 SAL_CALL getDriverMajorVersion( ) override;
+ virtual sal_Int32 SAL_CALL getDriverMinorVersion( ) override;
+ virtual sal_Bool SAL_CALL usesLocalFiles( ) override;
+ virtual sal_Bool SAL_CALL usesLocalFilePerTable( ) override;
+ virtual sal_Bool SAL_CALL supportsMixedCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesUpperCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesLowerCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesMixedCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL supportsMixedCaseQuotedIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesUpperCaseQuotedIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesLowerCaseQuotedIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesMixedCaseQuotedIdentifiers( ) override;
+ virtual OUString SAL_CALL getIdentifierQuoteString( ) override;
+ virtual OUString SAL_CALL getSQLKeywords( ) override;
+ virtual OUString SAL_CALL getNumericFunctions( ) override;
+ virtual OUString SAL_CALL getStringFunctions( ) override;
+ virtual OUString SAL_CALL getSystemFunctions( ) override;
+ virtual OUString SAL_CALL getTimeDateFunctions( ) override;
+ virtual OUString SAL_CALL getSearchStringEscape( ) override;
+ virtual OUString SAL_CALL getExtraNameCharacters( ) override;
+ virtual sal_Bool SAL_CALL supportsAlterTableWithAddColumn( ) override;
+ virtual sal_Bool SAL_CALL supportsAlterTableWithDropColumn( ) override;
+ virtual sal_Bool SAL_CALL supportsColumnAliasing( ) override;
+ virtual sal_Bool SAL_CALL nullPlusNonNullIsNull( ) override;
+ virtual sal_Bool SAL_CALL supportsTypeConversion( ) override;
+ virtual sal_Bool SAL_CALL supportsConvert( sal_Int32 fromType, sal_Int32 toType ) override;
+ virtual sal_Bool SAL_CALL supportsTableCorrelationNames( ) override;
+ virtual sal_Bool SAL_CALL supportsDifferentTableCorrelationNames( ) override;
+ virtual sal_Bool SAL_CALL supportsExpressionsInOrderBy( ) override;
+ virtual sal_Bool SAL_CALL supportsOrderByUnrelated( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupBy( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupByUnrelated( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupByBeyondSelect( ) override;
+ virtual sal_Bool SAL_CALL supportsLikeEscapeClause( ) override;
+ virtual sal_Bool SAL_CALL supportsMultipleResultSets( ) override;
+ virtual sal_Bool SAL_CALL supportsMultipleTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsNonNullableColumns( ) override;
+ virtual sal_Bool SAL_CALL supportsMinimumSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsCoreSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsExtendedSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92EntryLevelSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92IntermediateSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92FullSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsIntegrityEnhancementFacility( ) override;
+ virtual sal_Bool SAL_CALL supportsOuterJoins( ) override;
+ virtual sal_Bool SAL_CALL supportsFullOuterJoins( ) override;
+ virtual sal_Bool SAL_CALL supportsLimitedOuterJoins( ) override;
+ virtual OUString SAL_CALL getSchemaTerm( ) override;
+ virtual OUString SAL_CALL getProcedureTerm( ) override;
+ virtual OUString SAL_CALL getCatalogTerm( ) override;
+ virtual sal_Bool SAL_CALL isCatalogAtStart( ) override;
+ virtual OUString SAL_CALL getCatalogSeparator( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInDataManipulation( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInProcedureCalls( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInTableDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInIndexDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInPrivilegeDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInDataManipulation( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInProcedureCalls( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInTableDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInIndexDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInPrivilegeDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsPositionedDelete( ) override;
+ virtual sal_Bool SAL_CALL supportsPositionedUpdate( ) override;
+ virtual sal_Bool SAL_CALL supportsSelectForUpdate( ) override;
+ virtual sal_Bool SAL_CALL supportsStoredProcedures( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInComparisons( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInExists( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInIns( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInQuantifieds( ) override;
+ virtual sal_Bool SAL_CALL supportsCorrelatedSubqueries( ) override;
+ virtual sal_Bool SAL_CALL supportsUnion( ) override;
+ virtual sal_Bool SAL_CALL supportsUnionAll( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossCommit( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossRollback( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossCommit( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossRollback( ) override;
+ virtual sal_Int32 SAL_CALL getMaxBinaryLiteralLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCharLiteralLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInGroupBy( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInIndex( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInOrderBy( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInSelect( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInTable( ) override;
+ virtual sal_Int32 SAL_CALL getMaxConnections( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCursorNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxIndexLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxSchemaNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxProcedureNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCatalogNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxRowSize( ) override;
+ virtual sal_Bool SAL_CALL doesMaxRowSizeIncludeBlobs( ) override;
+ virtual sal_Int32 SAL_CALL getMaxStatementLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxStatements( ) override;
+ virtual sal_Int32 SAL_CALL getMaxTableNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxTablesInSelect( ) override;
+ virtual sal_Int32 SAL_CALL getMaxUserNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getDefaultTransactionIsolation( ) override;
+ virtual sal_Bool SAL_CALL supportsTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsTransactionIsolationLevel( sal_Int32 level ) override;
+ virtual sal_Bool SAL_CALL supportsDataDefinitionAndDataManipulationTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsDataManipulationTransactionsOnly( ) override;
+ virtual sal_Bool SAL_CALL dataDefinitionCausesTransactionCommit( ) override;
+ virtual sal_Bool SAL_CALL dataDefinitionIgnoredInTransactions( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getProcedures( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& procedureNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getProcedureColumns( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& procedureNamePattern, const OUString& columnNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTables( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const css::uno::Sequence< OUString >& types ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getSchemas( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getCatalogs( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTableTypes( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getColumns( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const OUString& columnNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getColumnPrivileges( const css::uno::Any& catalog, const OUString& schema, const OUString& table, const OUString& columnNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTablePrivileges( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getBestRowIdentifier( const css::uno::Any& catalog, const OUString& schema, const OUString& table, sal_Int32 scope, sal_Bool nullable ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getVersionColumns( const css::uno::Any& catalog, const OUString& schema, const OUString& table ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getPrimaryKeys( const css::uno::Any& catalog, const OUString& schema, const OUString& table ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getImportedKeys( const css::uno::Any& catalog, const OUString& schema, const OUString& table ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getExportedKeys( const css::uno::Any& catalog, const OUString& schema, const OUString& table ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getCrossReference( const css::uno::Any& primaryCatalog, const OUString& primarySchema, const OUString& primaryTable, const css::uno::Any& foreignCatalog, const OUString& foreignSchema, const OUString& foreignTable ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTypeInfo( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getIndexInfo( const css::uno::Any& catalog, const OUString& schema, const OUString& table, sal_Bool unique, sal_Bool approximate ) override;
+ virtual sal_Bool SAL_CALL supportsResultSetType( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL supportsResultSetConcurrency( sal_Int32 setType, sal_Int32 concurrency ) override;
+ virtual sal_Bool SAL_CALL ownUpdatesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL ownDeletesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL ownInsertsAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersUpdatesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersDeletesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersInsertsAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL updatesAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL deletesAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL insertsAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL supportsBatchUpdates( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getUDTs( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& typeNamePattern, const css::uno::Sequence< sal_Int32 >& types ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_driver.cxx b/connectivity/source/drivers/postgresql/pq_driver.cxx
new file mode 100644
index 000000000..09fe61ab2
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_driver.cxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+
+#include "pq_driver.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::lang::XSingleComponentFactory;
+using com::sun::star::lang::XServiceInfo;
+using com::sun::star::lang::XComponent;
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::XComponentContext;
+using com::sun::star::uno::Any;
+
+using com::sun::star::beans::PropertyValue;
+
+using com::sun::star::sdbc::XConnection;
+using com::sun::star::sdbc::DriverPropertyInfo;
+
+using com::sun::star::sdbcx::XTablesSupplier;
+
+
+namespace pq_sdbc_driver
+{
+
+Reference< XConnection > Driver::connect(
+ const OUString& url,const Sequence< PropertyValue >& info )
+{
+ if( ! acceptsURL( url ) ) // XDriver spec tells me to do so ...
+ return Reference< XConnection > ();
+
+ Sequence< Any > seq{ Any(url), Any(info) };
+ return Reference< XConnection> (
+ m_smgr->createInstanceWithArgumentsAndContext(
+ "org.openoffice.comp.connectivity.pq.Connection.noext",
+ seq, m_ctx ),
+ UNO_QUERY );
+}
+
+sal_Bool Driver::acceptsURL( const OUString& url )
+{
+ return url.startsWith( "sdbc:postgresql:" );
+}
+
+Sequence< DriverPropertyInfo > Driver::getPropertyInfo(
+ const OUString&,const Sequence< PropertyValue >& )
+{
+ return Sequence< DriverPropertyInfo > ();
+}
+
+sal_Int32 Driver::getMajorVersion( )
+{
+ return PQ_SDBC_MAJOR;
+}
+
+
+sal_Int32 Driver::getMinorVersion( )
+{
+ return PQ_SDBC_MINOR;
+}
+
+ // XServiceInfo
+OUString SAL_CALL Driver::getImplementationName()
+{
+ return "org.openoffice.comp.connectivity.pq.Driver.noext";
+}
+
+sal_Bool Driver::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > Driver::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdbc.Driver" };
+}
+
+// XComponent
+void Driver::disposing()
+{
+
+}
+
+
+Reference< XTablesSupplier > Driver::getDataDefinitionByConnection(
+ const Reference< XConnection >& connection )
+{
+ return Reference< XTablesSupplier >( connection , UNO_QUERY );
+}
+
+Reference< XTablesSupplier > Driver::getDataDefinitionByURL(
+ const OUString& url, const Sequence< PropertyValue >& info )
+{
+ return Reference< XTablesSupplier > ( connect( url, info ), UNO_QUERY );
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+connectivity_pq_sdbc_driver_get_implementation(
+ css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new pq_sdbc_driver::Driver(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_driver.hxx b/connectivity/source/drivers/postgresql/pq_driver.hxx
new file mode 100644
index 000000000..31d407f36
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_driver.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <sal/macros.h>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace pq_sdbc_driver
+{
+
+#define PQ_SDBC_DRIVER_VERSION SAL_STRINGIFY(PQ_SDBC_MAJOR) "." \
+ SAL_STRINGIFY(PQ_SDBC_MINOR) "." \
+ SAL_STRINGIFY(PQ_SDBC_MICRO)
+
+// use this to switch off sdbc support !
+// typedef cppu::WeakComponentImplHelper<
+// css::sdbc::XDriver,
+// css::lang::XServiceInfo
+// > DriverBase ;
+typedef cppu::WeakComponentImplHelper<
+ css::sdbc::XDriver,
+ css::lang::XServiceInfo,
+ css::sdbcx::XDataDefinitionSupplier > DriverBase ;
+class Driver : public cppu::BaseMutex, public DriverBase
+{
+ css::uno::Reference< css::uno::XComponentContext > m_ctx;
+ css::uno::Reference< css::lang::XMultiComponentFactory > m_smgr;
+
+public:
+ explicit Driver ( const css::uno::Reference < css::uno::XComponentContext > & ctx )
+ : DriverBase( m_aMutex ),
+ m_ctx( ctx ),
+ m_smgr( ctx->getServiceManager() )
+ {}
+
+public: // XDriver
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL connect(
+ const OUString& url,
+ const css::uno::Sequence< css::beans::PropertyValue >& info ) override;
+
+ virtual sal_Bool SAL_CALL acceptsURL( const OUString& url ) override;
+
+ virtual css::uno::Sequence< css::sdbc::DriverPropertyInfo > SAL_CALL getPropertyInfo(
+ const OUString& url,
+ const css::uno::Sequence< css::beans::PropertyValue >& info ) override;
+
+ virtual sal_Int32 SAL_CALL getMajorVersion( ) override;
+ virtual sal_Int32 SAL_CALL getMinorVersion( ) override;
+
+public:
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XDataDefinitionSupplier
+ virtual css::uno::Reference< css::sdbcx::XTablesSupplier > SAL_CALL
+ getDataDefinitionByConnection(
+ const css::uno::Reference< css::sdbc::XConnection >& connection ) override;
+ virtual css::uno::Reference< css::sdbcx::XTablesSupplier > SAL_CALL
+ getDataDefinitionByURL(
+ const OUString& url,
+ const css::uno::Sequence< css::beans::PropertyValue >& info ) override;
+
+ // XComponent
+ virtual void SAL_CALL disposing() override;
+
+};
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.cxx b/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.cxx
new file mode 100644
index 000000000..a75897ccb
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.cxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include "pq_fakedupdateableresultset.hxx"
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XResultSetUpdate;
+using com::sun::star::sdbc::XRowUpdate;
+
+namespace pq_sdbc_driver
+{
+
+FakedUpdateableResultSet::FakedUpdateableResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ ConnectionSettings **pSettings,
+ PGresult *result,
+ const OUString &schema,
+ const OUString &table,
+ const OUString &aReason )
+ : ResultSet( mutex, owner, pSettings, result, schema, table ),
+ m_aReason( aReason )
+{}
+
+
+css::uno::Any FakedUpdateableResultSet::queryInterface(
+ const css::uno::Type & reqType )
+{
+ Any ret = ResultSet::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< XResultSetUpdate * > ( this ),
+ static_cast< XRowUpdate * > ( this ) );
+ return ret;
+}
+
+
+css::uno::Sequence< css::uno::Type > FakedUpdateableResultSet::getTypes()
+{
+ static cppu::OTypeCollection s_collection(
+ cppu::UnoType<XResultSetUpdate>::get(),
+ cppu::UnoType<XRowUpdate>::get(),
+ ResultSet::getTypes());
+
+ return s_collection.getTypes();
+
+}
+
+css::uno::Sequence< sal_Int8> FakedUpdateableResultSet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void FakedUpdateableResultSet::insertRow( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateRow( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::deleteRow( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+ }
+
+void FakedUpdateableResultSet::cancelRowUpdates( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::moveToInsertRow( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::moveToCurrentRow( )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+
+void FakedUpdateableResultSet::updateNull( sal_Int32 /* columnIndex */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateBoolean( sal_Int32 /* columnIndex */, sal_Bool /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateByte( sal_Int32 /* columnIndex */, sal_Int8 /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateShort( sal_Int32 /* columnIndex */, sal_Int16 /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateInt( sal_Int32 /* columnIndex */, sal_Int32 /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateLong( sal_Int32 /* columnIndex */, sal_Int64 /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateFloat( sal_Int32 /* columnIndex */, float /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateDouble( sal_Int32 /* columnIndex */, double /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateString( sal_Int32 /* columnIndex */, const OUString& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateBytes( sal_Int32 /* columnIndex */, const css::uno::Sequence< sal_Int8 >& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateDate( sal_Int32 /* columnIndex */, const css::util::Date& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateTime( sal_Int32 /* columnIndex */, const css::util::Time& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateTimestamp( sal_Int32 /* columnIndex */, const css::util::DateTime& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateBinaryStream( sal_Int32 /* columnIndex */, const css::uno::Reference< css::io::XInputStream >& /* x */, sal_Int32 /* length */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateCharacterStream( sal_Int32 /* columnIndex */, const css::uno::Reference< css::io::XInputStream >& /* x */, sal_Int32 /* length */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateObject( sal_Int32 /* columnIndex */, const css::uno::Any& /* x */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+void FakedUpdateableResultSet::updateNumericObject( sal_Int32 /* columnIndex */, const css::uno::Any& /* x */, sal_Int32 /* scale */ )
+{
+ throw SQLException( m_aReason, *this, OUString(),1,Any() );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.hxx b/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.hxx
new file mode 100644
index 000000000..c2907aeb0
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_fakedupdateableresultset.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+
+#include "pq_resultset.hxx"
+
+namespace pq_sdbc_driver
+{
+/** necessary to avoid crashes in OOo, when an updateable result set is requested,
+ but cannot be delivered.
+ */
+class FakedUpdateableResultSet :
+ public ResultSet,
+ public css::sdbc::XResultSetUpdate,
+ public css::sdbc::XRowUpdate
+{
+ OUString m_aReason;
+
+public:
+ FakedUpdateableResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ ConnectionSettings **pSettings,
+ PGresult *result,
+ const OUString &schema,
+ const OUString &table,
+ const OUString &aReason );
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ResultSet::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ResultSet::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XResultSetUpdate
+ virtual void SAL_CALL insertRow( ) override;
+ virtual void SAL_CALL updateRow( ) override;
+ virtual void SAL_CALL deleteRow( ) override;
+ virtual void SAL_CALL cancelRowUpdates( ) override;
+ virtual void SAL_CALL moveToInsertRow( ) override;
+ virtual void SAL_CALL moveToCurrentRow( ) override;
+
+public: // XRowUpdate
+ virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) override;
+ virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) override;
+ virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) override;
+ virtual void SAL_CALL updateString( sal_Int32 columnIndex, const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) override;
+
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_preparedstatement.cxx b/connectivity/source/drivers/postgresql/pq_preparedstatement.cxx
new file mode 100644
index 000000000..2f31b4226
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_preparedstatement.cxx
@@ -0,0 +1,738 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include "pq_preparedstatement.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+#include "pq_statement.hxx"
+
+#include <o3tl/safeint.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+
+
+#include <comphelper/sequence.hxx>
+
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <memory>
+#include <string.h>
+#include <string_view>
+
+#include <connectivity/dbconversion.hxx>
+
+using osl::MutexGuard;
+
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::UNO_QUERY;
+
+using com::sun::star::lang::IllegalArgumentException;
+
+using com::sun::star::sdbc::XCloseable;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XRef;
+using com::sun::star::sdbc::XBlob;
+using com::sun::star::sdbc::XClob;
+using com::sun::star::sdbc::XArray;
+using com::sun::star::sdbc::XConnection;
+using com::sun::star::sdbc::SQLException;
+
+using com::sun::star::beans::Property;
+using com::sun::star::beans::XPropertySetInfo;
+
+using namespace dbtools;
+
+namespace pq_sdbc_driver
+{
+static ::cppu::IPropertyArrayHelper & getPreparedStatementPropertyArrayHelper()
+{
+ static ::cppu::OPropertyArrayHelper arrayHelper(
+ Sequence<Property>{
+ Property(
+ "CursorName", 0,
+ ::cppu::UnoType<OUString>::get() , 0 ),
+ Property(
+ "EscapeProcessing", 1,
+ cppu::UnoType<bool>::get() , 0 ),
+ Property(
+ "FetchDirection", 2,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "FetchSize", 3,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "MaxFieldSize", 4,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "MaxRows", 5,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "QueryTimeOut", 6,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "ResultSetConcurrency", 7,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "ResultSetType", 8,
+ ::cppu::UnoType<sal_Int32>::get() , 0 )},
+ true );
+ static ::cppu::IPropertyArrayHelper *pArrayHelper = &arrayHelper;
+
+ return *pArrayHelper;
+}
+
+static bool isOperator( char c )
+{
+ static const char * const operators = "<>=()!/&%.,;";
+
+ const char * w = operators;
+ while (*w && *w != c)
+ {
+ ++w;
+ }
+ return *w != 0;
+}
+
+static bool isNamedParameterStart( std::string_view o , int index )
+{
+ return o[index] == ':' && (
+ isWhitespace( o[index-1] ) || isOperator(o[index-1]) );
+}
+
+static bool isQuoted( std::string_view str )
+{
+ return str[0] == '"' || str[0] == '\'';
+}
+
+PreparedStatement::PreparedStatement(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< XConnection > & conn,
+ struct ConnectionSettings *pSettings,
+ const OString & stmt )
+ : PreparedStatement_BASE(refMutex->GetMutex())
+ , OPropertySetHelper(PreparedStatement_BASE::rBHelper)
+ , m_connection(conn)
+ , m_pSettings(pSettings)
+ , m_stmt(stmt)
+ , m_xMutex(refMutex)
+ , m_multipleResultAvailable(false)
+ , m_multipleResultUpdateCount(0)
+ , m_lastOidInserted( InvalidOid )
+{
+ m_props[PREPARED_STATEMENT_QUERY_TIME_OUT] <<= sal_Int32(0);
+ m_props[PREPARED_STATEMENT_MAX_ROWS] <<= sal_Int32(0);
+ m_props[PREPARED_STATEMENT_RESULT_SET_CONCURRENCY] <<=
+ css::sdbc::ResultSetConcurrency::READ_ONLY;
+ m_props[PREPARED_STATEMENT_RESULT_SET_TYPE] <<=
+ css::sdbc::ResultSetType::SCROLL_INSENSITIVE;
+
+ splitSQL( m_stmt, m_splittedStatement );
+ int elements = 0;
+ for(const OString & str : m_splittedStatement)
+ {
+ // ignore quoted strings...
+ if( ! isQuoted( str ) )
+ {
+ // the ':' cannot be the first or the last part of the
+ // token,
+ // the ? cannot be the first part of the token , so we start
+ // at one
+ for( int index = 1 ; index < str.getLength() ; index ++ )
+ {
+ if( str[index] == '?' ||
+ isNamedParameterStart( str , index )
+ )
+ {
+ elements ++;
+ }
+ }
+ }
+ }
+ m_vars = std::vector< OString >( elements );
+}
+
+PreparedStatement::~PreparedStatement()
+{
+}
+
+void PreparedStatement::checkColumnIndex( sal_Int32 parameterIndex )
+{
+ if( parameterIndex < 1 || o3tl::make_unsigned(parameterIndex) > m_vars.size() )
+ {
+ throw SQLException(
+ "pq_preparedstatement: parameter index out of range (expected 1 to "
+ + OUString::number( m_vars.size() )
+ + ", got " + OUString::number( parameterIndex )
+ + ", statement '" + OStringToOUString( m_stmt, ConnectionSettings::encoding )
+ + "')",
+ *this, OUString(), 1, Any () );
+ }
+}
+void PreparedStatement::checkClosed()
+{
+ if( ! m_pSettings || ! m_pSettings->pConnection )
+ throw SQLException(
+ "pq_driver: PreparedStatement or connection has already been closed !",
+ *this, OUString(),1,Any());
+}
+
+Any PreparedStatement::queryInterface( const Type & rType )
+{
+ Any aRet = PreparedStatement_BASE::queryInterface(rType);
+ return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
+}
+
+
+Sequence< Type > PreparedStatement::getTypes()
+{
+ static Sequence< Type > collection(
+ ::comphelper::concatSequences(
+ OPropertySetHelper::getTypes(),
+ PreparedStatement_BASE::getTypes()));
+
+ return collection;
+}
+
+Sequence< sal_Int8> PreparedStatement::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void PreparedStatement::close( )
+{
+ // let the connection die without acquired mutex !
+ Reference< XConnection > r;
+ Reference< XCloseable > resultSet;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ m_pSettings = nullptr;
+ r = m_connection;
+ m_connection.clear();
+
+ resultSet = m_lastResultset;
+ m_lastResultset.clear();
+ }
+ if( resultSet.is() )
+ {
+ resultSet->close();
+ }
+}
+
+void PreparedStatement::raiseSQLException( const char * errorMsg )
+{
+ OUStringBuffer buf(128);
+ buf.append( "pq_driver: ");
+ buf.append(
+ OUString( errorMsg, strlen(errorMsg) , ConnectionSettings::encoding ) );
+ buf.append( " (caused by statement '" );
+ buf.appendAscii( m_executedStatement.getStr() );
+ buf.append( "')" );
+ OUString error = buf.makeStringAndClear();
+ SAL_WARN("connectivity.postgresql", error);
+ throw SQLException( error, *this, OUString(), 1, Any() );
+}
+
+Reference< XResultSet > PreparedStatement::executeQuery( )
+{
+ if( ! execute( ) )
+ {
+ raiseSQLException( "not a query" );
+ }
+ return Reference< XResultSet > ( m_lastResultset, css::uno::UNO_QUERY );
+}
+
+sal_Int32 PreparedStatement::executeUpdate( )
+{
+ if( execute( ) )
+ {
+ raiseSQLException( "not a command" );
+ }
+ return m_multipleResultUpdateCount;
+}
+
+sal_Bool PreparedStatement::execute( )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ OStringBuffer buf( m_stmt.getLength() *2 );
+
+ std::vector< OString >::size_type vars = 0;
+ for(const OString & str : m_splittedStatement)
+ {
+ // LEM TODO: instead of this manual mucking with SQL
+ // could we use PQexecParams / PQExecPrepared / ...?
+ // Only snafu is giving the types of the parameters and
+ // that it needs $1, $2, etc instead of "?"
+
+// printf( "Split %d %s\n" , i , str.getStr() );
+ if( isQuoted( str ) )
+ {
+ buf.append( str );
+ }
+ else
+ {
+ int start = 0,index;
+ for( index = 1 ; index < str.getLength() ; index ++ )
+ {
+ if( str[index] == '?' )
+ {
+ buf.append( str.getStr()+start, index - start );
+ buf.append( m_vars[vars] );
+ vars ++;
+ start =index+1;
+ }
+ else
+ {
+ if ( isNamedParameterStart( str, index ) )
+ {
+ buf.append( str.getStr()+start, index -start );
+ buf.append( m_vars[vars] );
+
+ // skip to the end of the named parameter
+ while ( index < str.getLength()
+ && !( isWhitespace(str[index])
+ || isOperator (str[index])))
+ {
+ ++index;
+ }
+ start = index;
+ vars ++;
+ }
+ }
+ }
+// if( index +1 >= str.getLength() )
+// {
+ buf.append( str.getStr() + start, index -start );
+// }
+ }
+ }
+
+ m_executedStatement = buf.makeStringAndClear();
+
+ Reference< XCloseable > lastResultSet = m_lastResultset;
+ if( lastResultSet.is() )
+ lastResultSet->close();
+
+ m_lastResultset.clear();
+ m_lastTableInserted.clear();
+
+ struct CommandData data;
+ data.refMutex = m_xMutex;
+ data.ppSettings = &m_pSettings;
+ data.pLastOidInserted = &m_lastOidInserted;
+ data.pLastQuery = &m_lastQuery;
+ data.pMultipleResultUpdateCount = &m_multipleResultUpdateCount;
+ data.pMultipleResultAvailable = &m_multipleResultAvailable;
+ data.pLastTableInserted = &m_lastTableInserted;
+ data.pLastResultset = &m_lastResultset;
+ data.owner = *this;
+ data.tableSupplier.set( m_connection, UNO_QUERY );
+ data.concurrency = extractIntProperty( this, getStatics().RESULT_SET_CONCURRENCY );
+
+ return executePostgresCommand( m_executedStatement , &data ); // see pq_statement.cxx
+}
+
+Reference< XConnection > PreparedStatement::getConnection( )
+{
+ Reference< XConnection > ret;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ ret = m_connection;
+ }
+ return ret;
+}
+
+
+void PreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = OString( "NULL" );
+}
+
+void PreparedStatement::setObjectNull(
+ sal_Int32 parameterIndex, sal_Int32, const OUString& )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = OString( "NULL" );
+}
+
+
+void PreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ if( x )
+ m_vars[parameterIndex-1] = OString( "'t'" );
+ else
+ m_vars[parameterIndex-1] = OString( "'f'" );
+}
+
+void PreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
+{
+ setInt(parameterIndex,x);
+}
+
+void PreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
+{
+ setInt(parameterIndex, x );
+}
+
+void PreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
+{
+// printf( "setString %d %d\n ", parameterIndex, x);
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = "'" + OString::number(x) + "'";
+}
+
+void PreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = "'" + OString::number(x) + "'";
+}
+
+void PreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = "'" + OString::number(x) + "'";
+}
+
+void PreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ m_vars[parameterIndex-1] = "'" + OString::number(x) + "'";
+}
+
+void PreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
+{
+// printf( "setString %d %s\n ", parameterIndex,
+// OUStringToOString( x , RTL_TEXTENCODING_ASCII_US ).getStr());
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ OStringBuffer buf( 20 );
+ buf.append( "'" );
+ OString y = OUStringToOString( x, ConnectionSettings::encoding );
+ buf.ensureCapacity( y.getLength() * 2 + 2 );
+ int len = PQescapeString( const_cast<char*>(buf.getStr())+1, y.getStr() , y.getLength() );
+ buf.setLength( 1 + len );
+ buf.append( "'" );
+ m_vars[parameterIndex-1] = buf.makeStringAndClear();
+}
+
+void PreparedStatement::setBytes(
+ sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ checkClosed();
+ checkColumnIndex( parameterIndex );
+ size_t len;
+ const std::unique_ptr<unsigned char, deleter_from_fn<PQfreemem>> escapedString(
+ PQescapeBytea( reinterpret_cast<unsigned char const *>(x.getConstArray()), x.getLength(), &len));
+ if( ! escapedString )
+ {
+ throw SQLException(
+ "pq_preparedstatement.setBytes: Error during converting bytesequence to an SQL conform string",
+ *this, OUString(), 1, Any() );
+ }
+ m_vars[parameterIndex-1]
+ = OString::Concat("'") + std::string_view(reinterpret_cast<char *>(escapedString.get()), len -1) + "'";
+}
+
+
+void PreparedStatement::setDate( sal_Int32 parameterIndex, const css::util::Date& x )
+{
+ setString( parameterIndex, DBTypeConversion::toDateString( x ) );
+}
+
+void PreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& x )
+{
+ setString( parameterIndex, DBTypeConversion::toTimeString( x ) );
+}
+
+void PreparedStatement::setTimestamp(
+ sal_Int32 parameterIndex, const css::util::DateTime& x )
+{
+ setString( parameterIndex, DBTypeConversion::toDateTimeString( x ) );
+}
+
+void PreparedStatement::setBinaryStream(
+ sal_Int32,
+ const Reference< css::io::XInputStream >&,
+ sal_Int32 )
+{
+ throw SQLException(
+ "pq_preparedstatement: setBinaryStream not implemented",
+ *this, OUString(), 1, Any () );
+}
+
+void PreparedStatement::setCharacterStream(
+ sal_Int32,
+ const Reference< css::io::XInputStream >&,
+ sal_Int32 )
+{
+ throw SQLException(
+ "pq_preparedstatement: setCharacterStream not implemented",
+ *this, OUString(), 1, Any () );
+}
+
+void PreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
+{
+ if( ! implSetObject( this, parameterIndex, x ))
+ {
+ throw SQLException(
+ "pq_preparedstatement::setObject: can't convert value of type " + x.getValueTypeName(),
+ *this, OUString(), 1, Any () );
+ }
+}
+
+void PreparedStatement::setObjectWithInfo(
+ sal_Int32 parameterIndex,
+ const Any& x,
+ sal_Int32 targetSqlType,
+ sal_Int32 )
+{
+ if( css::sdbc::DataType::DECIMAL == targetSqlType ||
+ css::sdbc::DataType::NUMERIC == targetSqlType )
+ {
+ double myDouble = 0.0;
+ OUString myString;
+ if( x >>= myDouble )
+ {
+ myString = OUString::number( myDouble );
+ }
+ else
+ {
+ x >>= myString;
+ }
+ if( myString.isEmpty() )
+ {
+ throw SQLException(
+ "pq_preparedstatement::setObjectWithInfo: can't convert value of type "
+ + x.getValueTypeName() + " to type DECIMAL or NUMERIC",
+ *this, OUString(), 1, Any () );
+ }
+
+ setString( parameterIndex, myString );
+ }
+ else
+ {
+ setObject( parameterIndex, x );
+ }
+
+}
+
+void PreparedStatement::setRef(
+ sal_Int32,
+ const Reference< XRef >& )
+{
+ throw SQLException(
+ "pq_preparedstatement: setRef not implemented",
+ *this, OUString(), 1, Any () );
+}
+
+void PreparedStatement::setBlob(
+ sal_Int32,
+ const Reference< XBlob >& )
+{
+ throw SQLException(
+ "pq_preparedstatement: setBlob not implemented",
+ *this, OUString(), 1, Any () );
+}
+
+void PreparedStatement::setClob(
+ sal_Int32,
+ const Reference< XClob >& )
+{
+ throw SQLException(
+ "pq_preparedstatement: setClob not implemented",
+ *this, OUString(), 1, Any () );
+}
+
+void PreparedStatement::setArray(
+ sal_Int32 parameterIndex,
+ const Reference< XArray >& x )
+{
+ setString( parameterIndex, array2String( x->getArray( nullptr ) ) );
+}
+
+void PreparedStatement::clearParameters( )
+{
+ MutexGuard guard(m_xMutex->GetMutex() );
+ m_vars = std::vector< OString >( m_vars.size() );
+}
+
+Any PreparedStatement::getWarnings( )
+{
+ return Any();
+}
+
+void PreparedStatement::clearWarnings( )
+{
+}
+
+Reference< css::sdbc::XResultSetMetaData > PreparedStatement::getMetaData()
+{
+ Reference< css::sdbc::XResultSetMetaData > ret;
+ Reference< css::sdbc::XResultSetMetaDataSupplier > supplier( m_lastResultset, UNO_QUERY );
+ if( supplier.is() )
+ ret = supplier->getMetaData();
+ return ret;
+}
+
+::cppu::IPropertyArrayHelper & PreparedStatement::getInfoHelper()
+{
+ return getPreparedStatementPropertyArrayHelper();
+}
+
+
+sal_Bool PreparedStatement::convertFastPropertyValue(
+ Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ bool bRet;
+ rOldValue = m_props[nHandle];
+ switch( nHandle )
+ {
+ case PREPARED_STATEMENT_CURSOR_NAME:
+ {
+ OUString val;
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ case PREPARED_STATEMENT_ESCAPE_PROCESSING:
+ {
+ bool val(false);
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ case PREPARED_STATEMENT_FETCH_DIRECTION:
+ case PREPARED_STATEMENT_FETCH_SIZE:
+ case PREPARED_STATEMENT_MAX_FIELD_SIZE:
+ case PREPARED_STATEMENT_MAX_ROWS:
+ case PREPARED_STATEMENT_QUERY_TIME_OUT:
+ case PREPARED_STATEMENT_RESULT_SET_CONCURRENCY:
+ case PREPARED_STATEMENT_RESULT_SET_TYPE:
+ {
+ sal_Int32 val;
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ default:
+ {
+ throw IllegalArgumentException(
+ "pq_statement: Invalid property handle ("
+ + OUString::number( nHandle ) + ")",
+ *this, 2 );
+ }
+ }
+ return bRet;
+}
+
+
+void PreparedStatement::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,const Any& rValue )
+{
+ m_props[nHandle] = rValue;
+}
+
+void PreparedStatement::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ rValue = m_props[nHandle];
+}
+
+Reference < XPropertySetInfo > PreparedStatement::getPropertySetInfo()
+{
+ return OPropertySetHelper::createPropertySetInfo( getPreparedStatementPropertyArrayHelper() );
+}
+
+void PreparedStatement::disposing()
+{
+ close();
+}
+
+
+Reference< XResultSet > PreparedStatement::getResultSet( )
+{
+ return Reference< XResultSet > ( m_lastResultset, css::uno::UNO_QUERY );
+}
+sal_Int32 PreparedStatement::getUpdateCount( )
+{
+ return m_multipleResultUpdateCount;
+}
+sal_Bool PreparedStatement::getMoreResults( )
+{
+ Reference< XCloseable > lastResultSet = m_lastResultset;
+ if( lastResultSet.is() )
+ lastResultSet->close();
+ m_multipleResultUpdateCount = -1;
+ return false;
+}
+
+Reference< XResultSet > PreparedStatement::getGeneratedValues( )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ return getGeneratedValuesFromLastInsert(
+ m_pSettings, m_connection, m_lastOidInserted, m_lastTableInserted, m_lastQuery );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_preparedstatement.hxx b/connectivity/source/drivers/postgresql/pq_preparedstatement.hxx
new file mode 100644
index 000000000..4755efbe0
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_preparedstatement.hxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+#include <vector>
+
+#include <libpq-fe.h>
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/component.hxx>
+
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+#include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+
+#include "pq_connection.hxx"
+namespace pq_sdbc_driver
+{
+
+const sal_Int32 PREPARED_STATEMENT_CURSOR_NAME = 0;
+const sal_Int32 PREPARED_STATEMENT_ESCAPE_PROCESSING = 1;
+const sal_Int32 PREPARED_STATEMENT_FETCH_DIRECTION = 2;
+const sal_Int32 PREPARED_STATEMENT_FETCH_SIZE = 3;
+const sal_Int32 PREPARED_STATEMENT_MAX_FIELD_SIZE = 4;
+const sal_Int32 PREPARED_STATEMENT_MAX_ROWS = 5;
+const sal_Int32 PREPARED_STATEMENT_QUERY_TIME_OUT = 6;
+const sal_Int32 PREPARED_STATEMENT_RESULT_SET_CONCURRENCY = 7;
+const sal_Int32 PREPARED_STATEMENT_RESULT_SET_TYPE = 8;
+
+#define PREPARED_STATEMENT_SIZE 9
+
+typedef ::cppu::WeakComponentImplHelper< css::sdbc::XPreparedStatement,
+ css::sdbc::XParameters,
+ css::sdbc::XCloseable,
+ css::sdbc::XWarningsSupplier,
+ css::sdbc::XMultipleResults,
+ css::sdbc::XGeneratedResultSet,
+ css::sdbc::XResultSetMetaDataSupplier
+ > PreparedStatement_BASE;
+class PreparedStatement : public PreparedStatement_BASE,
+ public cppu::OPropertySetHelper
+{
+private:
+ css::uno::Any m_props[PREPARED_STATEMENT_SIZE];
+ css::uno::Reference< css::sdbc::XConnection > m_connection;
+ ConnectionSettings *m_pSettings;
+ css::uno::Reference< css::sdbc::XCloseable > m_lastResultset;
+ OString m_stmt;
+ OString m_executedStatement;
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ std::vector< OString > m_vars;
+ std::vector< OString > m_splittedStatement;
+ bool m_multipleResultAvailable;
+ sal_Int32 m_multipleResultUpdateCount;
+ sal_Int32 m_lastOidInserted;
+ OUString m_lastTableInserted;
+ OString m_lastQuery;
+
+public:
+ /**
+ * @param ppConnection The piece of memory, pConnection points to, is accessible
+ * as long as a reference to parameter con is held.
+ */
+ PreparedStatement( const rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection> & con,
+ struct ConnectionSettings *pSettings,
+ const OString &stmt );
+
+ virtual ~PreparedStatement() override;
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { PreparedStatement_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { PreparedStatement_BASE::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & reqType ) override;
+
+public: // XCloseable
+ virtual void SAL_CALL close( ) override;
+
+public: // XPreparedStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery() override;
+ virtual sal_Int32 SAL_CALL executeUpdate( ) override;
+ virtual sal_Bool SAL_CALL execute( ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+public: // XParameters
+ virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) override;
+ virtual void SAL_CALL setObjectNull(
+ sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) override;
+ virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) override;
+ virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) override;
+ virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) override;
+ virtual void SAL_CALL setString( sal_Int32 parameterIndex, const OUString& x ) override;
+ virtual void SAL_CALL setBytes(
+ sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL setTimestamp(
+ sal_Int32 parameterIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL setBinaryStream(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::io::XInputStream >& x,
+ sal_Int32 length ) override;
+ virtual void SAL_CALL setCharacterStream(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::io::XInputStream >& x,
+ sal_Int32 length ) override;
+ virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL setObjectWithInfo(
+ sal_Int32 parameterIndex,
+ const css::uno::Any& x,
+ sal_Int32 targetSqlType,
+ sal_Int32 scale ) override;
+ virtual void SAL_CALL setRef(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::sdbc::XRef >& x ) override;
+ virtual void SAL_CALL setBlob(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::sdbc::XBlob >& x ) override;
+ virtual void SAL_CALL setClob(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::sdbc::XClob >& x ) override;
+ virtual void SAL_CALL setArray(
+ sal_Int32 parameterIndex,
+ const css::uno::Reference< css::sdbc::XArray >& x ) override;
+ virtual void SAL_CALL clearParameters( ) override;
+
+public: // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // OPropertySetHelper
+ virtual cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+
+ void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle ) const override;
+
+ // XPropertySet
+ css::uno::Reference < css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+
+public: // XGeneratedResultSet
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL
+ getGeneratedValues( ) override;
+
+public: // XMultipleResults
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet( ) override;
+ virtual sal_Int32 SAL_CALL getUpdateCount( ) override;
+ virtual sal_Bool SAL_CALL getMoreResults( ) override;
+
+public: // XResultSetMetaDataSupplier (is required by framework (see
+ // dbaccess/source/core/api/preparedstatement.cxx::getMetaData() )
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+public: // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+private:
+ void checkColumnIndex( sal_Int32 parameterIndex );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkClosed();
+ /// @throws css::sdbc::SQLException
+ void raiseSQLException( const char * errorMsg );
+// PGresult *pgExecute( OString *pQuery );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_resultset.cxx b/connectivity/source/drivers/postgresql/pq_resultset.cxx
new file mode 100644
index 000000000..556bae92d
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_resultset.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include "pq_resultset.hxx"
+#include "pq_resultsetmetadata.hxx"
+
+#include <connectivity/dbexception.hxx>
+
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+
+using osl::MutexGuard;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XResultSetMetaData;
+
+
+namespace pq_sdbc_driver
+{
+
+void ResultSet::checkClosed()
+{
+ if( ! m_result )
+ {
+ throw SQLException( "pq_resultset: already closed",
+ *this, OUString(), 1, Any() );
+ }
+
+ if( ! m_ppSettings || ! *m_ppSettings || ! (*m_ppSettings)->pConnection )
+ {
+ throw SQLException( "pq_resultset: statement has been closed already",
+ *this, OUString(), 1, Any() );
+ }
+
+}
+
+ResultSet::ResultSet( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< XInterface > & owner,
+ ConnectionSettings **ppSettings,
+ PGresult * result,
+ const OUString &schema,
+ const OUString &table)
+ : BaseResultSet(
+ refMutex, owner, PQntuples( result ),
+ PQnfields( result ),(*ppSettings)->tc ),
+ m_result( result ),
+ m_schema( schema ),
+ m_table( table ),
+ m_ppSettings( ppSettings )
+{
+ // LEM TODO: shouldn't these things be inherited from the statement or something like that?
+ // Positioned update/delete not supported, so no cursor name
+ // Fetch direction and size are cursor-specific things, so not used now.
+ // Fetch size not set
+ m_props[ BASERESULTSET_FETCH_DIRECTION ] <<= css::sdbc::FetchDirection::UNKNOWN;
+ // No escape processing for now
+ m_props[ BASERESULTSET_ESCAPE_PROCESSING ] <<= false;
+ // Bookmarks not implemented for now
+ m_props[ BASERESULTSET_IS_BOOKMARKABLE ] <<= false;
+ m_props[ BASERESULTSET_RESULT_SET_CONCURRENCY ] <<= css::sdbc::ResultSetConcurrency::READ_ONLY;
+ m_props[ BASERESULTSET_RESULT_SET_TYPE ] <<= css::sdbc::ResultSetType::SCROLL_INSENSITIVE;
+}
+
+
+Any ResultSet::getValue( sal_Int32 columnIndex )
+{
+ Any ret;
+ if( PQgetisnull( m_result, m_row, columnIndex -1 ) )
+ {
+ m_wasNull = true;
+ }
+ else
+ {
+ m_wasNull = false;
+ ret <<= OUString(
+ PQgetvalue( m_result, m_row , columnIndex -1 ) ,
+ PQgetlength( m_result, m_row , columnIndex -1 ) ,
+ ConnectionSettings::encoding );
+
+ }
+ return ret;
+}
+
+ResultSet::~ResultSet()
+{}
+
+void ResultSet::close( )
+{
+ Reference< XInterface > owner;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ if( m_result )
+ {
+ PQclear(m_result );
+ m_result = nullptr;
+ m_row = -1;
+ }
+ owner = m_owner;
+ m_owner.clear();
+ }
+}
+
+Reference< XResultSetMetaData > ResultSet::getMetaData( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ return new ResultSetMetaData(
+ m_xMutex, this, this, m_ppSettings, m_result, m_schema, m_table );
+}
+
+sal_Int32 ResultSet::findColumn( const OUString& columnName )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ sal_Int32 res = PQfnumber( m_result,
+ OUStringToOString( columnName, ConnectionSettings::encoding ).getStr());
+ /* PQfnumber return -1 for not found, which is what we want
+ * other than that we use col number as 1-based not 0-based */
+ if(res >= 0)
+ {
+ res += 1;
+ }
+ else
+ {
+ ::dbtools::throwInvalidColumnException( columnName, *this );
+ assert(false);
+ }
+ return res;
+}
+
+static bool isNumber( const char * data, sal_Int32 len )
+{
+ bool ret = false;
+ if( len )
+ {
+ ret = true;
+ for( int i = 0 ; i < len ; i ++ )
+ {
+ if( ( data[i] >= '0' && data[i] <= '9' ) ||
+ data[i] == '-' || data[i] == '+' || data[i] == '.' || data[i] == ',' )
+ {
+ if( data[i] == '-' && i != 0 && i != len-1 )
+ {
+ // no number, maybe a date
+ ret = false;
+ break;
+ }
+ }
+ else
+ {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static bool isInteger( const char * data, sal_Int32 len )
+{
+ bool ret = false;
+ if( len )
+ {
+ ret = true;
+ for( int i = 0 ; i < len ; i ++ )
+ {
+ if( ( data[i] >= '0' && data[i] <= '9' ) ||
+ data[i] == '-' || data[i] == '+' )
+ {
+ if( data[i] == '-' && i != 0 && i != len-1 )
+ {
+ // no number, maybe a date
+ ret = false;
+ break;
+ }
+ }
+ else
+ {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static bool isDate( const char * data, sal_Int32 len )
+{
+ return 10 == len &&
+ '-' == data[4] &&
+ '-' == data[7] &&
+ isInteger( &(data[0]),4 ) &&
+ isInteger( &(data[5]),2) &&
+ isInteger( &(data[8]),2 );
+}
+
+static bool isTime( const char * data, sal_Int32 len )
+{
+ return 8 == len &&
+ ':' == data[2] &&
+ ':' == data[5] &&
+ isInteger( &(data[0]),2 ) &&
+ isInteger( &(data[3]),2) &&
+ isInteger( &(data[6]),2 );
+
+}
+
+static bool isTimestamp( const char * data, sal_Int32 len )
+{
+ return len == 19 && isDate( data, 10) && isTime( &(data[11]),8 );
+}
+
+sal_Int32 ResultSet::guessDataType( sal_Int32 column )
+{
+ // we don't look into more than 100 rows ...
+ sal_Int32 ret = css::sdbc::DataType::INTEGER;
+
+ int maxRows = std::min<sal_Int32>( m_rowCount, 100 );
+ for( int i = 0 ; i < maxRows ; i ++ )
+ {
+ if( ! PQgetisnull( m_result, i , column-1 ) )
+ {
+ const char * p = PQgetvalue( m_result, i , column -1 );
+ int len = PQgetlength( m_result, i , column -1 );
+
+ if( css::sdbc::DataType::INTEGER == ret )
+ {
+ if( ! isInteger( p,len ) )
+ ret = css::sdbc::DataType::NUMERIC;
+ }
+ if( css::sdbc::DataType::NUMERIC == ret )
+ {
+ if( ! isNumber( p,len ) )
+ {
+ ret = css::sdbc::DataType::DATE;
+ }
+ }
+ if( css::sdbc::DataType::DATE == ret )
+ {
+ if( ! isDate( p,len ) )
+ {
+ ret = css::sdbc::DataType::TIME;
+ }
+ }
+ if( css::sdbc::DataType::TIME == ret )
+ {
+ if( ! isTime( p,len ) )
+ {
+ ret = css::sdbc::DataType::TIMESTAMP;
+ }
+ }
+ if( css::sdbc::DataType::TIMESTAMP == ret )
+ {
+ if( ! isTimestamp( p,len ) )
+ {
+ ret = css::sdbc::DataType::LONGVARCHAR;
+ break;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_resultset.hxx b/connectivity/source/drivers/postgresql/pq_resultset.hxx
new file mode 100644
index 000000000..340e34b70
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_resultset.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/component.hxx>
+
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include "pq_connection.hxx"
+#include "pq_baseresultset.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class ResultSet : public BaseResultSet
+{
+protected:
+ PGresult *m_result;
+ OUString m_schema;
+ OUString m_table;
+ ConnectionSettings **m_ppSettings;
+
+protected:
+ /** mutex should be locked before called
+ */
+ virtual void checkClosed() override;
+
+ /** unchecked, acquire mutex before calling
+ */
+ virtual css::uno::Any getValue( sal_Int32 columnIndex ) override;
+
+public:
+ ResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ ConnectionSettings **pSettings,
+ PGresult *result,
+ const OUString &schema,
+ const OUString &table );
+ virtual ~ResultSet() override;
+
+public: // XCloseable
+ virtual void SAL_CALL close( ) override;
+
+public: // XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+public: // XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName ) override;
+
+public:
+ sal_Int32 guessDataType( sal_Int32 column );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_resultsetmetadata.cxx b/connectivity/source/drivers/postgresql/pq_resultsetmetadata.cxx
new file mode 100644
index 000000000..fbe10f82d
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_resultsetmetadata.cxx
@@ -0,0 +1,441 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ustrbuf.hxx>
+
+#include "pq_resultsetmetadata.hxx"
+#include "pq_resultset.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+
+#include <string.h>
+
+using osl::MutexGuard;
+
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::UNO_QUERY;
+
+
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbcx::XColumnsSupplier;
+using com::sun::star::sdbcx::XTablesSupplier;
+
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::container::XNameAccess;
+
+
+namespace pq_sdbc_driver
+{
+
+// struct ColumnMetaData
+// {
+// OUString tableName;
+// OUString schemaTableName;
+// OUString typeName;
+// css::sdbc::DataType type;
+// sal_Int32 precision;
+// sal_Int32 scale;
+// sal_Bool isCurrency;
+// sal_Bool isNullable;
+// sal_Bool isAutoIncrement;
+// sal_Bool isReadOnly;
+// sal_Bool isSigned;
+// };
+
+// is not exported by the postgres header
+const int PQ_VARHDRSZ = sizeof( sal_Int32 );
+
+static void extractPrecisionAndScale( sal_Int32 atttypmod, sal_Int32 *precision, sal_Int32 *scale )
+{
+ if( atttypmod < PQ_VARHDRSZ )
+ {
+ *precision = 0;
+ *scale = 0;
+ }
+ else
+ {
+ if( atttypmod & 0xffff0000 )
+ {
+ *precision = ( ( atttypmod - PQ_VARHDRSZ ) >> 16 ) & 0xffff;
+ *scale = (atttypmod - PQ_VARHDRSZ ) & 0xffff;
+ }
+ else
+ {
+ *precision = atttypmod - PQ_VARHDRSZ;
+ *scale = 0;
+ }
+ }
+}
+
+ResultSetMetaData::ResultSetMetaData(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XResultSet > & origin,
+ ResultSet * pResultSet,
+ ConnectionSettings **ppSettings,
+ PGresult const *pResult,
+ const OUString &schemaName,
+ const OUString &tableName ) :
+ m_xMutex( refMutex ),
+ m_ppSettings( ppSettings ),
+ m_origin( origin ),
+ m_tableName( tableName ),
+ m_schemaName( schemaName ),
+ m_colDesc( PQnfields( pResult ) ),
+ m_pResultSet( pResultSet ),
+ m_checkedForTable( false ),
+ m_checkedForTypes( false ),
+ m_colCount( PQnfields( pResult ) )
+{
+
+ // extract all needed information from the result object, so that we don't
+ // need it anymore after this call !
+ for( int col = 0; col < m_colCount ; col ++ )
+ {
+ sal_Int32 size = PQfsize( pResult, col );
+ size = -1 == size ? 25 : size;
+ m_colDesc[col].displaySize = size;
+
+ extractPrecisionAndScale(
+ PQfmod( pResult, col ),
+ & ( m_colDesc[col].precision ),
+ & ( m_colDesc[col].scale ) );
+ char *name = PQfname( pResult, col );
+ m_colDesc[col].name = OUString( name, strlen(name) , ConnectionSettings::encoding );
+ m_colDesc[col].typeOid = PQftype( pResult, col );
+ m_colDesc[col].type = css::sdbc::DataType::LONGVARCHAR;
+ }
+}
+
+void ResultSetMetaData::checkForTypes()
+{
+ if( m_checkedForTypes )
+ return;
+
+ Reference< XStatement > stmt =
+ extractConnectionFromStatement( m_origin->getStatement() )->createStatement();
+ DisposeGuard guard( stmt );
+ OUStringBuffer buf(128);
+ buf.append( "SELECT oid, typname, typtype FROM pg_type WHERE ");
+ for( int i = 0 ; i < m_colCount ; i ++ )
+ {
+ if( i > 0 )
+ buf.append( " OR " );
+ int oid = m_colDesc[i].typeOid;
+ buf.append( "oid=" );
+ buf.append( static_cast<sal_Int32>(oid) );
+ }
+ Reference< XResultSet > rs = stmt->executeQuery( buf.makeStringAndClear() );
+ Reference< XRow > xRow( rs, UNO_QUERY );
+ while( rs->next() )
+ {
+ Oid oid = xRow->getInt( 1 );
+ OUString typeName = xRow->getString( 2 );
+ OUString typType = xRow->getString( 3 );
+
+ sal_Int32 type = typeNameToDataType( typeName, typType );
+
+ for( sal_Int32 j = 0; j < m_colCount ; j ++ )
+ {
+ if( m_colDesc[j].typeOid == oid )
+ {
+ m_colDesc[j].typeName = typeName;
+ m_colDesc[j].type = type;
+ }
+ }
+ }
+ m_checkedForTypes = true;
+}
+
+void ResultSetMetaData::checkTable()
+{
+ if( m_checkedForTable )
+ return;
+
+ m_checkedForTable = true;
+ if( !m_tableName.getLength() )
+ return;
+
+ Reference< css::container::XNameAccess > tables = (*m_ppSettings)->tables;
+ if( ! tables.is() )
+ {
+
+ Reference< XTablesSupplier > supplier(
+ extractConnectionFromStatement( m_origin->getStatement() ), UNO_QUERY);
+ if( supplier.is() )
+ tables = supplier->getTables();
+ }
+ if( tables.is() )
+ {
+ const OUString name (getTableName ( 1 ));
+ const OUString schema (getSchemaName( 1 ));
+ const OUString composedName( schema.isEmpty() ? name : (schema + "." + name) );
+ tables->getByName( composedName ) >>= m_table;
+ }
+}
+
+sal_Int32 ResultSetMetaData::getIntColumnProperty( const OUString & name, int index, int def )
+{
+ sal_Int32 ret = def; // give defensive answers, when data is not available
+ try
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( index );
+ Reference< XPropertySet > set = getColumnByIndex( index );
+
+ if( set.is() )
+ {
+ set->getPropertyValue( name ) >>= ret;
+ }
+ }
+ catch( css::uno::Exception & )
+ {
+ }
+ return ret;
+}
+
+bool ResultSetMetaData::getBoolColumnProperty( const OUString & name, int index, bool def )
+{
+ bool ret = def;
+ try
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( index );
+ Reference< XPropertySet > set = getColumnByIndex( index );
+ if( set.is() )
+ {
+ set->getPropertyValue( name ) >>= ret;
+ }
+ }
+ catch( css::uno::Exception & )
+ {
+ }
+
+ return ret;
+}
+
+Reference< css::beans::XPropertySet > ResultSetMetaData::getColumnByIndex( int index )
+{
+ Reference< XPropertySet > ret;
+ checkTable();
+ if( m_table.is() )
+ {
+ OUString columnName = getColumnName( index );
+ Reference< XColumnsSupplier > supplier( m_table, UNO_QUERY );
+ if( supplier.is() )
+ {
+ Reference< XNameAccess > columns = supplier->getColumns();
+ if( columns.is() && columns->hasByName( columnName ) )
+ {
+ columns->getByName( columnName ) >>= ret;
+ }
+ }
+ }
+ return ret;
+}
+
+// Methods
+sal_Int32 ResultSetMetaData::getColumnCount( )
+{
+ return m_colCount;
+}
+
+sal_Bool ResultSetMetaData::isAutoIncrement( sal_Int32 column )
+{
+
+ bool ret = getBoolColumnProperty( getStatics().IS_AUTO_INCREMENT, column, false );
+ return ret;
+}
+
+sal_Bool ResultSetMetaData::isCaseSensitive( sal_Int32 )
+{
+ return true; // ??? hmm, numeric types or
+}
+
+sal_Bool ResultSetMetaData::isSearchable( sal_Int32 )
+{
+ return true; // mmm, what types are not searchable ?
+}
+
+sal_Bool ResultSetMetaData::isCurrency( sal_Int32 column )
+{
+ return getBoolColumnProperty( getStatics().IS_CURRENCY, column, false );
+}
+
+sal_Int32 ResultSetMetaData::isNullable( sal_Int32 column )
+{
+ return getIntColumnProperty(
+ getStatics().IS_NULLABLE, column, css::sdbc::ColumnValue::NULLABLE_UNKNOWN );
+}
+
+sal_Bool ResultSetMetaData::isSigned( sal_Int32 )
+{
+ return true;
+}
+
+sal_Int32 ResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( column );
+ return m_colDesc[column-1].displaySize;
+}
+
+OUString ResultSetMetaData::getColumnLabel( sal_Int32 column )
+{
+ return getColumnName( column);
+}
+
+OUString ResultSetMetaData::getColumnName( sal_Int32 column )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( column );
+
+ return m_colDesc[column-1].name;
+}
+
+OUString ResultSetMetaData::getSchemaName( sal_Int32 )
+{
+ return m_schemaName;
+}
+
+sal_Int32 ResultSetMetaData::getPrecision( sal_Int32 column )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( column );
+ return m_colDesc[column-1].precision;
+}
+
+sal_Int32 ResultSetMetaData::getScale( sal_Int32 column )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( column );
+ return m_colDesc[column-1].scale;
+}
+
+OUString ResultSetMetaData::getTableName( sal_Int32 )
+{
+// LEM TODO This is very fishy... Should probably return the table to which that column belongs!
+ return m_tableName;
+}
+
+OUString ResultSetMetaData::getCatalogName( sal_Int32 )
+{
+ // can do this through XConnection.getCatalog() !
+ return OUString();
+}
+sal_Int32 ResultSetMetaData::getColumnType( sal_Int32 column )
+{
+ int ret = getIntColumnProperty( getStatics().TYPE, column, -100 );
+ if( -100 == ret )
+ {
+ checkForTypes();
+ if( css::sdbc::DataType::LONGVARCHAR == m_colDesc[column-1].type && m_pResultSet )
+ m_colDesc[column-1].type = m_pResultSet->guessDataType( column );
+ ret = m_colDesc[column-1].type;
+ }
+ return ret;
+}
+
+OUString ResultSetMetaData::getColumnTypeName( sal_Int32 column )
+{
+ OUString ret; // give defensive answers, when data is not available
+ try
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkColumnIndex( column );
+ Reference< XPropertySet > set = getColumnByIndex( column );
+
+ if( set.is() )
+ {
+ set->getPropertyValue( getStatics().TYPE_NAME ) >>= ret;
+ }
+ else
+ {
+ checkForTypes();
+ ret = m_colDesc[column-1].typeName;
+ }
+ }
+ catch( css::uno::Exception & )
+ {
+ }
+ return ret;
+}
+
+
+sal_Bool ResultSetMetaData::isReadOnly( sal_Int32 )
+{
+ return false;
+}
+
+sal_Bool ResultSetMetaData::isWritable( sal_Int32 column )
+{
+ return ! isReadOnly( column ); // what's the sense if this method ?
+}
+
+sal_Bool ResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
+{
+ return isWritable(column); // uhh, now it becomes really esoteric...
+}
+OUString ResultSetMetaData::getColumnServiceName( sal_Int32 )
+{
+ return OUString();
+}
+
+void ResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
+{
+ if( columnIndex < 1 || columnIndex > m_colCount )
+ {
+ throw SQLException(
+ "pq_resultsetmetadata: index out of range (expected 1 to "
+ + OUString::number( m_colCount ) + ", got " + OUString::number( columnIndex ),
+ *this, OUString(), 1, Any() );
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_resultsetmetadata.hxx b/connectivity/source/drivers/postgresql/pq_resultsetmetadata.hxx
new file mode 100644
index 000000000..67e34d44d
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_resultsetmetadata.hxx
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+#include <vector>
+
+#include "pq_connection.hxx"
+
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace pq_sdbc_driver
+{
+
+struct ColDesc
+{
+ OUString name;
+ sal_Int32 precision;
+ sal_Int32 scale;
+ sal_Int32 displaySize;
+ Oid typeOid;
+ OUString typeName;
+ sal_Int32 type;
+};
+
+class ResultSet;
+
+class ResultSetMetaData :
+ public ::cppu::WeakImplHelper< css::sdbc::XResultSetMetaData >
+{
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ ConnectionSettings **m_ppSettings;
+ css::uno::Reference< css::sdbc::XResultSet > m_origin;
+ css::uno::Reference< css::beans::XPropertySet > m_table;
+ OUString m_tableName;
+ OUString m_schemaName;
+ std::vector< ColDesc > m_colDesc;
+ ResultSet *m_pResultSet;
+
+ bool m_checkedForTable;
+ bool m_checkedForTypes;
+
+ sal_Int32 m_colCount;
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkColumnIndex( sal_Int32 columnIndex );
+ void checkTable();
+ void checkForTypes();
+ css::uno::Reference< css::beans::XPropertySet > getColumnByIndex( int index );
+
+ sal_Int32 getIntColumnProperty( const OUString & name, int index, int def );
+ bool getBoolColumnProperty( const OUString & name, int index, bool def );
+
+public:
+ ResultSetMetaData(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & reMutex,
+ const css::uno::Reference< css::sdbc::XResultSet > & origin,
+ ResultSet *pResultSet,
+ ConnectionSettings **pSettings,
+ PGresult const *pResult,
+ const OUString &schemaName,
+ const OUString &tableName );
+
+public:
+ // Methods
+ virtual sal_Int32 SAL_CALL getColumnCount( ) override;
+ virtual sal_Bool SAL_CALL isAutoIncrement( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCaseSensitive( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSearchable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCurrency( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL isNullable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSigned( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnDisplaySize( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnLabel( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getSchemaName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getPrecision( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getScale( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getTableName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getCatalogName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnType( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnTypeName( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isWritable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isDefinitelyWritable( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnServiceName( sal_Int32 column ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_sequenceresultset.cxx b/connectivity/source/drivers/postgresql/pq_sequenceresultset.cxx
new file mode 100644
index 000000000..defb99906
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_sequenceresultset.cxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+
+#include "pq_sequenceresultset.hxx"
+#include "pq_sequenceresultsetmetadata.hxx"
+
+#include <connectivity/dbexception.hxx>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+using com::sun::star::sdbc::XResultSetMetaData;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Any;
+
+namespace pq_sdbc_driver
+{
+
+void SequenceResultSet::checkClosed()
+{
+ // we never close :o)
+}
+
+
+Any SequenceResultSet::getValue( sal_Int32 columnIndex )
+{
+ m_wasNull = ! m_data[m_row][columnIndex -1 ].hasValue();
+ return m_data[m_row][columnIndex -1 ];
+}
+
+SequenceResultSet::SequenceResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ std::vector< OUString >&& colNames,
+ std::vector< std::vector< Any > >&& data,
+ const Reference< css::script::XTypeConverter > & tc,
+ const ColumnMetaDataVector *pVec) :
+ BaseResultSet( mutex, owner, data.size(), colNames.size(), tc ),
+ m_data(std::move(data) ),
+ m_columnNames( std::move(colNames) )
+{
+ if( pVec )
+ {
+ m_meta = new SequenceResultSetMetaData( std::vector(*pVec), m_columnNames.size() );
+ }
+}
+
+SequenceResultSet::~SequenceResultSet()
+{
+
+}
+
+void SequenceResultSet::close( )
+{
+ // a noop
+}
+
+Reference< XResultSetMetaData > SAL_CALL SequenceResultSet::getMetaData( )
+{
+ if( ! m_meta.is() )
+ {
+ // Oh no, not again
+ throw css::sdbc::SQLException(
+ "pq_sequenceresultset: no meta supported ", *this,
+ // I did not find "IM001" in a specific standard,
+ // but it seems to be used by other systems (such as ODBC)
+ // and some parts of LibreOffice special-case it.
+ "IM001", 1, Any() );
+ }
+ return m_meta;
+}
+
+
+sal_Int32 SAL_CALL SequenceResultSet::findColumn(
+ const OUString& columnName )
+{
+ // no need to guard, as all members are readonly !
+ for( int i = 0 ;i < m_fieldCount ; i ++ )
+ {
+ if( columnName == m_columnNames[i] )
+ {
+ return i+1;
+ }
+ }
+ ::dbtools::throwInvalidColumnException( columnName, *this );
+ assert(false);
+ return 0; // Never reached
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_sequenceresultset.hxx b/connectivity/source/drivers/postgresql/pq_sequenceresultset.hxx
new file mode 100644
index 000000000..64ac212b6
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_sequenceresultset.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/component.hxx>
+
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include "pq_connection.hxx"
+#include "pq_baseresultset.hxx"
+#include "pq_statics.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class SequenceResultSet : public BaseResultSet
+{
+protected:
+ std::vector< std::vector< css::uno::Any > > m_data;
+
+ std::vector< OUString > m_columnNames;
+ css::uno::Reference< css::sdbc::XResultSetMetaData > m_meta;
+
+protected:
+ /** mutex should be locked before called
+ */
+ virtual void checkClosed() override;
+
+ /** unchecked, acquire mutex before calling
+ */
+ virtual css::uno::Any getValue( sal_Int32 columnIndex ) override;
+
+public:
+ SequenceResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ std::vector< OUString >&& colNames,
+ std::vector< std::vector< css::uno::Any > >&& data,
+ const css::uno::Reference< css::script::XTypeConverter > &tc,
+ const ColumnMetaDataVector *pVec = nullptr);
+ virtual ~SequenceResultSet() override;
+
+public: // XCloseable
+ virtual void SAL_CALL close( ) override;
+
+public: // XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+public: // XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.cxx b/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.cxx
new file mode 100644
index 000000000..568e6bb9f
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.cxx
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 200? by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include "pq_sequenceresultsetmetadata.hxx"
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+using com::sun::star::uno::Any;
+
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+SequenceResultSetMetaData::SequenceResultSetMetaData(
+ ColumnMetaDataVector&& metaDataVector,
+ int colCount ) :
+ m_columnData( std::move(metaDataVector) ),
+ m_colCount( colCount )
+{
+}
+
+
+// Methods
+sal_Int32 SequenceResultSetMetaData::getColumnCount( )
+{
+ return m_colCount;
+}
+
+sal_Bool SequenceResultSetMetaData::isAutoIncrement( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].isAutoIncrement;
+}
+
+sal_Bool SequenceResultSetMetaData::isCaseSensitive( sal_Int32 /* column */ )
+{
+
+ return true; // ??? hmm, numeric types or
+}
+
+sal_Bool SequenceResultSetMetaData::isSearchable( sal_Int32 /* column */ )
+{
+ return true; // mmm, what types are not searchable ?
+}
+
+sal_Bool SequenceResultSetMetaData::isCurrency( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].isCurrency;
+}
+
+sal_Int32 SequenceResultSetMetaData::isNullable( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].isNullable ? 1 : 0;
+}
+
+sal_Bool SequenceResultSetMetaData::isSigned( sal_Int32 /* column */ )
+{
+ return true;
+}
+
+sal_Int32 SequenceResultSetMetaData::getColumnDisplaySize( sal_Int32 /* column */ )
+{
+ return 50;
+}
+
+OUString SequenceResultSetMetaData::getColumnLabel( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].columnName;
+}
+
+OUString SequenceResultSetMetaData::getColumnName( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].columnName;
+}
+
+OUString SequenceResultSetMetaData::getSchemaName( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].schemaTableName;
+}
+
+
+sal_Int32 SequenceResultSetMetaData::getPrecision( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].precision;
+}
+
+sal_Int32 SequenceResultSetMetaData::getScale( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].scale;
+}
+
+OUString SequenceResultSetMetaData::getTableName( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].tableName;
+}
+
+OUString SequenceResultSetMetaData::getCatalogName( sal_Int32 /* column */ )
+{
+ // can do this through XConnection.getCatalog() !
+ return OUString();
+}
+sal_Int32 SequenceResultSetMetaData::getColumnType( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].type;
+}
+
+OUString SequenceResultSetMetaData::getColumnTypeName( sal_Int32 column )
+{
+ checkColumnIndex( column );
+ return m_columnData[column-1].typeName;
+}
+
+
+sal_Bool SequenceResultSetMetaData::isReadOnly( sal_Int32 /* column */ )
+{
+ return false;
+}
+
+sal_Bool SequenceResultSetMetaData::isWritable( sal_Int32 column )
+{
+ return ! isReadOnly( column ); // what's the sense if this method ?
+}
+
+sal_Bool SequenceResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
+{
+ return isWritable(column); // uhh, now it becomes really esoteric...
+}
+OUString SequenceResultSetMetaData::getColumnServiceName( sal_Int32 /* column */ )
+{
+ return OUString();
+}
+
+void SequenceResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
+{
+ if( columnIndex < 1 || columnIndex > m_colCount )
+ {
+ throw SQLException(
+ "pq_sequenceresultsetmetadata: index out of range (expected 1 to "
+ + OUString::number( m_colCount )
+ + ", got " + OUString::number( columnIndex ),
+ *this, OUString(), 1, Any() );
+ }
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.hxx b/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.hxx
new file mode 100644
index 000000000..3cd32ff66
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_sequenceresultsetmetadata.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 200? by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_statics.hxx"
+
+namespace pq_sdbc_driver
+{
+ class SequenceResultSetMetaData :
+ public ::cppu::WeakImplHelper< css::sdbc::XResultSetMetaData >
+ {
+ ColumnMetaDataVector m_columnData;
+ sal_Int32 m_colCount;
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkColumnIndex( sal_Int32 columnIndex );
+
+ public:
+ SequenceResultSetMetaData(
+ ColumnMetaDataVector&& vec,
+ int colCount );
+
+ public:
+ // Methods
+ virtual sal_Int32 SAL_CALL getColumnCount( ) override;
+ virtual sal_Bool SAL_CALL isAutoIncrement( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCaseSensitive( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSearchable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCurrency( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL isNullable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSigned( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnDisplaySize( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnLabel( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getSchemaName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getPrecision( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getScale( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getTableName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getCatalogName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnType( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnTypeName( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isWritable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isDefinitelyWritable( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnServiceName( sal_Int32 column ) override;
+ };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_statement.cxx b/connectivity/source/drivers/postgresql/pq_statement.cxx
new file mode 100644
index 000000000..7db4b2053
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_statement.cxx
@@ -0,0 +1,888 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include "pq_statement.hxx"
+#include "pq_fakedupdateableresultset.hxx"
+#include "pq_updateableresultset.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+#include <osl/time.h>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <comphelper/sequence.hxx>
+
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+
+#include <string.h>
+#include <string_view>
+
+using osl::MutexGuard;
+
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::UNO_QUERY;
+
+using com::sun::star::lang::IllegalArgumentException;
+
+using com::sun::star::sdbc::XCloseable;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XPreparedStatement;
+using com::sun::star::sdbc::XParameters;
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XConnection;
+using com::sun::star::sdbc::SQLException;
+
+using com::sun::star::sdbcx::XColumnsSupplier;
+using com::sun::star::sdbcx::XKeysSupplier;
+
+using com::sun::star::beans::Property;
+using com::sun::star::beans::XPropertySetInfo;
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::container::XNameAccess;
+using com::sun::star::container::XEnumerationAccess;
+using com::sun::star::container::XEnumeration;
+using com::sun::star::container::XIndexAccess;
+
+namespace pq_sdbc_driver
+{
+static ::cppu::IPropertyArrayHelper & getStatementPropertyArrayHelper()
+{
+ static ::cppu::OPropertyArrayHelper arrayHelper(
+ Sequence<Property>{
+ Property(
+ "CursorName", 0,
+ ::cppu::UnoType<OUString>::get() , 0 ),
+ Property(
+ "EscapeProcessing", 1,
+ cppu::UnoType<bool>::get() , 0 ),
+ Property(
+ "FetchDirection", 2,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "FetchSize", 3,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "MaxFieldSize", 4,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "MaxRows", 5,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "QueryTimeOut", 6,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "ResultSetConcurrency", 7,
+ ::cppu::UnoType<sal_Int32>::get() , 0 ),
+ Property(
+ "ResultSetType", 8,
+ ::cppu::UnoType<sal_Int32>::get() , 0 )},
+ true );
+
+ return arrayHelper;
+}
+
+Statement::Statement( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< XConnection > & conn,
+ struct ConnectionSettings *pSettings )
+ : Statement_BASE( refMutex->GetMutex() )
+ , OPropertySetHelper( Statement_BASE::rBHelper )
+ , m_connection( conn )
+ , m_pSettings( pSettings )
+ , m_xMutex( refMutex )
+ , m_multipleResultAvailable(false)
+ , m_multipleResultUpdateCount(0)
+ , m_lastOidInserted(InvalidOid)
+{
+ m_props[STATEMENT_QUERY_TIME_OUT] <<= sal_Int32(0);
+ m_props[STATEMENT_MAX_ROWS] <<= sal_Int32(0);
+ m_props[STATEMENT_RESULT_SET_CONCURRENCY] <<=
+ css::sdbc::ResultSetConcurrency::READ_ONLY;
+ m_props[STATEMENT_RESULT_SET_TYPE] <<=
+ css::sdbc::ResultSetType::SCROLL_INSENSITIVE;
+}
+
+Statement::~Statement()
+{
+}
+
+void Statement::checkClosed()
+{
+ if( ! m_pSettings || ! m_pSettings->pConnection )
+ throw SQLException(
+ "pq_driver: Statement or connection has already been closed !",
+ *this, OUString(),1,Any());
+}
+
+Any Statement::queryInterface( const Type & rType )
+{
+ Any aRet = Statement_BASE::queryInterface(rType);
+ return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
+}
+
+
+Sequence< Type > Statement::getTypes()
+{
+ static Sequence< Type > collection(
+ ::comphelper::concatSequences(
+ OPropertySetHelper::getTypes(),
+ Statement_BASE::getTypes()));
+
+ return collection;
+}
+
+Sequence< sal_Int8> Statement::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void Statement::close( )
+{
+ // let the connection die without acquired mutex !
+ Reference< XConnection > r;
+ Reference< XCloseable > resultSet;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ m_pSettings = nullptr;
+ r = m_connection;
+ m_connection.clear();
+
+ resultSet = m_lastResultset;
+ m_lastResultset.clear();
+ }
+ if( resultSet.is() )
+ {
+ resultSet->close();
+ }
+
+}
+
+void Statement::raiseSQLException(
+ std::u16string_view sql, const char * errorMsg )
+{
+ OUString error = "pq_driver: "
+ + OUString( errorMsg, strlen(errorMsg), ConnectionSettings::encoding )
+ + " (caused by statement '" + sql + "')";
+ SAL_WARN("connectivity.postgresql", error);
+ throw SQLException( error, *this, OUString(), 1, Any() );
+}
+
+Reference< XResultSet > Statement::executeQuery(const OUString& sql )
+{
+ if( ! execute( sql ) )
+ {
+ raiseSQLException( sql, "not a query" );
+ }
+ return Reference< XResultSet > ( m_lastResultset, css::uno::UNO_QUERY );
+}
+
+sal_Int32 Statement::executeUpdate( const OUString& sql )
+{
+ if( execute( sql ) )
+ {
+ raiseSQLException( sql, "not a command" );
+ }
+ return m_multipleResultUpdateCount;
+}
+
+/// @throws SQLException
+static void raiseSQLException(
+ const Reference< XInterface> & owner,
+ std::string_view sql,
+ const char * errorMsg,
+ const char *errorType = nullptr )
+{
+ OUStringBuffer buf(128);
+ buf.append( "pq_driver: ");
+ if( errorType )
+ {
+ buf.append( "[" );
+ buf.appendAscii( errorType );
+ buf.append( "]" );
+ }
+ buf.append(
+ OUString( errorMsg, strlen(errorMsg) , ConnectionSettings::encoding ) );
+ buf.append( " (caused by statement '" );
+ buf.append( OStringToOUString( sql, ConnectionSettings::encoding ) );
+ buf.append( "')" );
+ OUString error = buf.makeStringAndClear();
+ SAL_WARN("connectivity.postgresql", error);
+ throw SQLException( error, owner, OUString(), 1, Any() );
+}
+
+
+// returns the elements of the primary key of the given table
+// static Sequence< Reference< css::beans::XPropertySet > > lookupKeys(
+static std::vector< OUString > lookupKeys(
+ const Reference< css::container::XNameAccess > &tables,
+ const OUString & table,
+ OUString *pSchema,
+ OUString *pTable)
+{
+ std::vector< OUString > ret;
+ Reference< XKeysSupplier > keySupplier;
+ Statics & st = getStatics();
+
+ if( tables->hasByName( table ) )
+ tables->getByName( table ) >>= keySupplier;
+ else if( -1 == table.indexOf( '.' ) )
+ {
+ // it wasn't a fully qualified name. Now need to skip through all tables.
+ Reference< XEnumerationAccess > enumerationAccess( tables, UNO_QUERY );
+
+ Reference< css::container::XEnumeration > enumeration =
+ enumerationAccess->createEnumeration();
+ while( enumeration->hasMoreElements() )
+ {
+ Reference< XPropertySet > set;
+ enumeration->nextElement() >>= set;
+ OUString name;
+// OUString schema;
+
+ if( set->getPropertyValue( st.NAME ) >>= name )
+ {
+// printf( "searching %s %s\n",
+// OUStringToOString( schema, RTL_TEXTENCODING_ASCII_US ).getStr(),
+// OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ if( name == table )
+ {
+
+ if( keySupplier.is() )
+ {
+ // is ambiguous, as I don't know postgresql searchpath,
+ // I can't continue here, as I may write to a different table
+ keySupplier.clear();
+ SAL_INFO("connectivity.postgresql", "Can't offer updateable result set because table " << name << " is duplicated, add schema to resolve ambiguity");
+ break;
+ }
+ keySupplier.set( set, UNO_QUERY );
+ }
+ }
+ }
+ }
+ else
+ {
+ SAL_INFO("connectivity.postgresql", "Can't offer updateable result set ( table " << table << " is unknown)");
+ }
+
+ if( keySupplier.is() )
+ {
+ Reference< XPropertySet > set( keySupplier, UNO_QUERY );
+ set->getPropertyValue( getStatics().NAME ) >>= *pTable;
+ set->getPropertyValue( getStatics().SCHEMA_NAME ) >>= *pSchema;
+ set.clear();
+
+ Reference< XEnumerationAccess > keys ( keySupplier->getKeys(), UNO_QUERY );
+ Reference< XEnumeration > enumeration = keys->createEnumeration();
+ while( enumeration->hasMoreElements() )
+ {
+ enumeration->nextElement() >>= set;
+ sal_Int32 keyType = 0;
+ if( (set->getPropertyValue( st.TYPE ) >>= keyType ) &&
+ keyType == css::sdbcx::KeyType::PRIMARY )
+ {
+ Reference< XColumnsSupplier > columns( set, UNO_QUERY );
+ Reference< XIndexAccess > indexAccess( columns->getColumns(), UNO_QUERY );
+
+ int length = indexAccess->getCount();
+ ret.resize( length );
+// printf( "primary key for Table %s is ",
+// OUStringToOString( table, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ for( int i = 0 ; i < length ; i ++ )
+ {
+ indexAccess->getByIndex( i ) >>= set;
+ OUString name;
+ set->getPropertyValue( st.NAME ) >>= name;
+ ret[i] = name;
+// printf( "%s," , OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ }
+// printf( "\n" );
+ }
+ }
+ if( ret.empty() )
+ {
+ SAL_INFO("connectivity.postgresql", "Can't offer updateable result set ( table " << table << " does not have a primary key)");
+ }
+ }
+ return ret;
+}
+
+bool executePostgresCommand( const OString & cmd, struct CommandData *data )
+{
+ ConnectionSettings *pSettings = *(data->ppSettings);
+
+ sal_Int32 duration = osl_getGlobalTimer();
+ PGresult *result = PQexec( pSettings->pConnection, cmd.getStr() );
+ duration = osl_getGlobalTimer() - duration;
+ if( ! result )
+ raiseSQLException(
+ data->owner, cmd, PQerrorMessage( pSettings->pConnection ) );
+
+ ExecStatusType state = PQresultStatus( result );
+ *(data->pLastOidInserted) = 0;
+ data->pLastTableInserted->clear();
+ *(data->pLastQuery) = cmd;
+
+ bool ret = false;
+ switch( state )
+ {
+ case PGRES_COMMAND_OK:
+ {
+ *(data->pMultipleResultUpdateCount) = atoi( PQcmdTuples( result ) );
+ *(data->pMultipleResultAvailable) = false;
+
+ // in case an oid value is available, we retrieve it
+ *(data->pLastOidInserted) = PQoidValue( result );
+
+ // in case it was a single insert, extract the name of the table,
+ // otherwise the table name is empty
+ *(data->pLastTableInserted) =
+ extractTableFromInsert( OStringToOUString( cmd, ConnectionSettings::encoding ) );
+
+ OString strMain = "executed command '" + cmd + "' successfully ('" + OString::number(*( data->pMultipleResultUpdateCount ))
+ + "), duration=" + OString::number(duration) + "ms";
+
+ OString strOption;
+ if( *(data->pLastOidInserted) )
+ {
+ strOption += ", usedOid=" + OString::number( *(data->pLastOidInserted) ) + ", diagnosedTable="
+ + OUStringToOString(*data->pLastTableInserted, ConnectionSettings::encoding);
+ }
+ SAL_INFO("connectivity.postgresql", strMain + strOption);
+ PQclear( result );
+ break;
+ }
+ case PGRES_TUPLES_OK: // success
+ {
+ // In case it is a single table, it has a primary key and all columns
+ // belonging to the primary key are in the result set, allow updateable result sets
+ // otherwise, don't
+ OUString table, schema;
+ std::vector< OString > vec;
+ tokenizeSQL( cmd, vec );
+ OUString sourceTable =
+ OStringToOUString(
+ extractSingleTableFromSelect( vec ), ConnectionSettings::encoding );
+
+ if( data->concurrency ==
+ css::sdbc::ResultSetConcurrency::UPDATABLE )
+ {
+ OString aReason;
+ if( sourceTable.getLength() )
+ {
+ std::vector< OUString > sourceTableKeys = lookupKeys(
+ pSettings->tables.is() ?
+ pSettings->tables : data->tableSupplier->getTables() ,
+ sourceTable,
+ &schema,
+ &table);
+
+ // check, whether the columns are in the result set (required !)
+ int i;
+ for( i = 0 ; i < static_cast<int>(sourceTableKeys.size()) ; i ++ )
+ {
+ if( -1 == PQfnumber(
+ result,
+ OUStringToOString( sourceTableKeys[i] ,
+ ConnectionSettings::encoding ).getStr()) )
+ {
+ break;
+ }
+ }
+
+ if( !sourceTableKeys.empty() && i == static_cast<int>(sourceTableKeys.size()) )
+ {
+ *(data->pLastResultset) =
+ UpdateableResultSet::createFromPGResultSet(
+ data->refMutex, data->owner, data->ppSettings, result,
+ schema, table, std::move(sourceTableKeys) );
+ }
+ else if( ! table.getLength() )
+ {
+ aReason = "can't support updateable resultset, because a single table in the "
+ "WHERE part of the statement could not be identified (" + cmd + ".";
+ }
+ else if( !sourceTableKeys.empty() )
+ {
+ aReason = "can't support updateable resultset for table "
+ + OUStringToOString( schema, ConnectionSettings::encoding ) + "."
+ + OUStringToOString( table, ConnectionSettings::encoding )
+ + ", because resultset does not contain a part of the primary key ( column "
+ + OUStringToOString( sourceTableKeys[i], ConnectionSettings::encoding )
+ + " is missing )";
+ }
+ else
+ {
+
+ aReason = "can't support updateable resultset for table "
+ + OUStringToOString( schema, ConnectionSettings::encoding ) + "."
+ + OUStringToOString( table, ConnectionSettings::encoding )
+ + ", because resultset table does not have a primary key ";
+ }
+ }
+ else
+ {
+ SAL_WARN("connectivity.postgresql", "can't support updateable result for selects with multiple tables (" << cmd << ")");
+ }
+ if( ! (*(data->pLastResultset)).is() )
+ {
+ SAL_WARN("connectivity.postgresql", aReason);
+
+ // TODO: How to react here correctly ?
+ // remove this piece of code
+ *(data->pLastResultset) =
+ new FakedUpdateableResultSet(
+ data->refMutex, data->owner,
+ data->ppSettings,result, schema, table,
+ OStringToOUString( aReason, ConnectionSettings::encoding) );
+ }
+
+ }
+ else if( sourceTable.getLength() > 0)
+ {
+ splitConcatenatedIdentifier( sourceTable, &schema, &table );
+ }
+
+ sal_Int32 returnedRows = PQntuples( result );
+ if( ! data->pLastResultset->is() )
+ *(data->pLastResultset) =
+ Reference< XCloseable > (
+ new ResultSet(
+ data->refMutex, data->owner,
+ data->ppSettings,result, schema, table ) );
+ *(data->pMultipleResultAvailable) = true;
+ ret = true;
+ SAL_INFO("connectivity.postgresql", "executed query '" << cmd << "' successfully, duration=" << duration << "ms, returnedRows=" << returnedRows << ".");
+ break;
+ }
+ case PGRES_EMPTY_QUERY:
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ case PGRES_BAD_RESPONSE:
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ default:
+ raiseSQLException(
+ data->owner, cmd, PQresultErrorMessage( result ) , PQresStatus( state ) );
+ }
+ return ret;
+
+}
+
+static Sequence< OUString > getPrimaryKeyColumnNames(
+ const Reference< XConnection > & connection, const OUString &schemaName, const OUString &tableName )
+{
+ Sequence< OUString > ret;
+
+ Int2StringMap mapIndex2Name;
+ fillAttnum2attnameMap( mapIndex2Name, connection, schemaName, tableName );
+
+ // retrieve the primary key ...
+ Reference< XPreparedStatement > stmt = connection->prepareStatement(
+ "SELECT conkey " // 7
+ "FROM pg_constraint INNER JOIN pg_class ON conrelid = pg_class.oid "
+ "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
+ "LEFT JOIN pg_class AS class2 ON confrelid = class2.oid "
+ "LEFT JOIN pg_namespace AS nmsp2 ON class2.relnamespace=nmsp2.oid "
+ "WHERE pg_class.relname = ? AND pg_namespace.nspname = ? AND pg_constraint.contype='p'" );
+ DisposeGuard guard( stmt );
+ Reference< XParameters > paras( stmt, UNO_QUERY );
+ paras->setString( 1 , tableName );
+ paras->setString( 2 , schemaName );
+ Reference< XResultSet > rs = stmt->executeQuery();
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ if( rs->next() )
+ {
+ ret = convertMappedIntArray2StringArray( mapIndex2Name, string2intarray(xRow->getString( 1 ) ) );
+ }
+ return ret;
+}
+
+static void getAutoValues(
+ String2StringMap & result,
+ const Reference< XConnection > & connection,
+ const OUString &schemaName,
+ const OUString & tableName,
+ const ConnectionSettings *pConnectionSettings )
+{
+ OUString strDefaultValue = getColExprForDefaultSettingVal(pConnectionSettings);
+ Reference< XPreparedStatement > stmt = connection->prepareStatement(
+ "SELECT pg_attribute.attname, " + strDefaultValue +
+ "FROM pg_class, pg_namespace, pg_attribute "
+ "LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND "
+ "pg_attribute.attnum = pg_attrdef.adnum "
+ "WHERE pg_attribute.attrelid = pg_class.oid AND "
+ "pg_class.relnamespace = pg_namespace.oid AND "
+ "pg_namespace.nspname = ? AND "
+ // LEM TODO: this is weird; why "LIKE" and not "="?
+ // Most probably gives problems if tableName contains '%'
+ "pg_class.relname LIKE ? AND "
+ + strDefaultValue + " != ''"
+ );
+ DisposeGuard guard( stmt );
+ Reference< XParameters > paras( stmt, UNO_QUERY );
+ paras->setString( 1 , schemaName );
+ paras->setString( 2 , tableName );
+ Reference< XResultSet > rs = stmt->executeQuery();
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ while( rs->next() )
+ {
+ result[ OUStringToOString( xRow->getString( 1 ), RTL_TEXTENCODING_ASCII_US) ] =
+ OUStringToOString( xRow->getString(2), RTL_TEXTENCODING_ASCII_US );
+ }
+}
+
+Reference< XResultSet > getGeneratedValuesFromLastInsert(
+ ConnectionSettings *pConnectionSettings,
+ const Reference< XConnection > &connection,
+ sal_Int32 nLastOid,
+ const OUString & lastTableInserted,
+ const OString & lastQuery )
+{
+ Reference< XResultSet > ret;
+ OUString query;
+ OUString schemaName, tableName;
+ splitConcatenatedIdentifier(
+ lastTableInserted, &schemaName, &tableName );
+
+ if( nLastOid && lastTableInserted.getLength() )
+ {
+ OUStringBuffer buf( 128 );
+ buf.append( "SELECT * FROM " );
+ if( schemaName.getLength() )
+ bufferQuoteQualifiedIdentifier(buf, schemaName, tableName, pConnectionSettings );
+ else
+ bufferQuoteIdentifier( buf, lastTableInserted, pConnectionSettings );
+ buf.append( " WHERE oid = " );
+ buf.append( nLastOid );
+ query = buf.makeStringAndClear();
+ }
+ else if ( lastTableInserted.getLength() && lastQuery.getLength() )
+ {
+ // extract nameValue Pairs
+ String2StringMap namedValues;
+ extractNameValuePairsFromInsert( namedValues, lastQuery );
+
+ // debug ...
+// OStringBuffer buf( 128);
+// buf.append( "extracting name/value from '" );
+// buf.append( lastQuery.getStr() );
+// buf.append( "' to [" );
+// for( String2StringMap::iterator ii = namedValues.begin() ; ii != namedValues.end() ; ++ii )
+// {
+// buf.append( ii->first.getStr() );
+// buf.append( "=" );
+// buf.append( ii->second.getStr() );
+// buf.append( "," );
+// }
+// buf.append( "]\n" );
+// printf( "%s", buf.makeStringAndClear() );
+
+ // TODO: make also unqualified tables names work here. Have a look at 2.8.3. The Schema Search Path
+ // in postgresql doc
+
+ const Sequence< OUString > keyColumnNames = getPrimaryKeyColumnNames( connection, schemaName, tableName );
+ if( keyColumnNames.hasElements() )
+ {
+ OUStringBuffer buf( 128 );
+ buf.append( "SELECT * FROM " );
+ bufferQuoteQualifiedIdentifier(buf, schemaName, tableName, pConnectionSettings );
+ buf.append( " WHERE " );
+ bool bAdditionalCondition = false;
+ String2StringMap autoValues;
+ for( OUString const & columnNameUnicode : keyColumnNames )
+ {
+ OUString value;
+ OString columnName = OUStringToOString( columnNameUnicode, ConnectionSettings::encoding );
+ bool bColumnMatchNamedValue = false;
+ for (auto const& namedValue : namedValues)
+ {
+ if( columnName.equalsIgnoreAsciiCase( namedValue.first ) )
+ {
+ value = OStringToOUString( namedValue.second , ConnectionSettings::encoding );
+ bColumnMatchNamedValue = true;
+ break;
+ }
+ }
+
+ // check, if a column of the primary key was not inserted explicitly,
+ if( !bColumnMatchNamedValue )
+ {
+ if( autoValues.empty() )
+ {
+ getAutoValues( autoValues, connection, schemaName, tableName, pConnectionSettings );
+ }
+ // this could mean, that the column is a default or auto value, check this ...
+ bool bColumnMatchAutoValue = false;
+ for (auto const& autoValue : autoValues)
+ {
+ if( columnName.equalsIgnoreAsciiCase( autoValue.first ) )
+ {
+ // it is indeed an auto value.
+ value = OStringToOUString(autoValue.second, RTL_TEXTENCODING_ASCII_US );
+ // check, whether it is a sequence
+
+ if( autoValue.second.startsWith("nextval(") )
+ {
+ // retrieve current sequence value:
+ OUStringBuffer myBuf(128 );
+ myBuf.append( "SELECT currval(" );
+ myBuf.appendAscii( &(autoValue.second.getStr()[8]));
+ value = querySingleValue( connection, myBuf.makeStringAndClear() );
+ }
+ bColumnMatchAutoValue = true;
+ break;
+ }
+ }
+ if( !bColumnMatchAutoValue )
+ {
+ // it even was no autovalue, no sense to continue as we can't query the
+ // inserted row
+ buf.truncate();
+ break;
+ }
+ }
+
+ if( bAdditionalCondition )
+ buf.append( " AND " );
+ bufferQuoteIdentifier( buf, columnNameUnicode, pConnectionSettings );
+ buf.append( " = " );
+ buf.append( value );
+ bAdditionalCondition = true;
+ }
+ query = buf.makeStringAndClear();
+ }
+ }
+
+ if( query.getLength() )
+ {
+ Reference< css::sdbc::XStatement > stmt = connection->createStatement();
+ ret = stmt->executeQuery( query );
+ }
+
+ return ret;
+
+}
+
+sal_Bool Statement::execute( const OUString& sql )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ OString cmd = OUStringToOString( sql, m_pSettings );
+
+ Reference< XCloseable > lastResultSetHolder = m_lastResultset;
+ if( lastResultSetHolder.is() )
+ lastResultSetHolder->close();
+
+ m_lastResultset.clear();
+ m_lastTableInserted.clear();
+
+ struct CommandData data;
+ data.refMutex = m_xMutex;
+ data.ppSettings = &m_pSettings;
+ data.pLastOidInserted = &m_lastOidInserted;
+ data.pLastQuery = &m_lastQuery;
+ data.pMultipleResultUpdateCount = &m_multipleResultUpdateCount;
+ data.pMultipleResultAvailable = &m_multipleResultAvailable;
+ data.pLastTableInserted = &m_lastTableInserted;
+ data.pLastResultset = &m_lastResultset;
+ data.owner = *this;
+ data.tableSupplier.set( m_connection, UNO_QUERY );
+ data.concurrency =
+ extractIntProperty( this, getStatics().RESULT_SET_CONCURRENCY );
+ return executePostgresCommand( cmd , &data );
+}
+
+Reference< XConnection > Statement::getConnection( )
+{
+ Reference< XConnection > ret;
+ {
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ ret = m_connection;
+ }
+ return ret;
+}
+
+
+Any Statement::getWarnings( )
+{
+ return Any();
+}
+
+void Statement::clearWarnings( )
+{
+}
+
+Reference< css::sdbc::XResultSetMetaData > Statement::getMetaData()
+{
+ Reference< css::sdbc::XResultSetMetaData > ret;
+ Reference< css::sdbc::XResultSetMetaDataSupplier > supplier( m_lastResultset, UNO_QUERY );
+ if( supplier.is() )
+ ret = supplier->getMetaData();
+ return ret;
+}
+
+
+::cppu::IPropertyArrayHelper & Statement::getInfoHelper()
+{
+ return getStatementPropertyArrayHelper();
+}
+
+
+sal_Bool Statement::convertFastPropertyValue(
+ Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue )
+{
+ rOldValue = m_props[nHandle];
+ bool bRet;
+ switch( nHandle )
+ {
+ case STATEMENT_CURSOR_NAME:
+ {
+ OUString val;
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ case STATEMENT_ESCAPE_PROCESSING:
+ {
+ bool val(false);
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ case STATEMENT_FETCH_DIRECTION:
+ case STATEMENT_FETCH_SIZE:
+ case STATEMENT_MAX_FIELD_SIZE:
+ case STATEMENT_MAX_ROWS:
+ case STATEMENT_QUERY_TIME_OUT:
+ case STATEMENT_RESULT_SET_CONCURRENCY:
+ case STATEMENT_RESULT_SET_TYPE:
+ {
+ sal_Int32 val;
+ bRet = ( rValue >>= val );
+ rConvertedValue <<= val;
+ break;
+ }
+ default:
+ {
+ throw IllegalArgumentException(
+ "pq_statement: Invalid property handle ("
+ + OUString::number( nHandle ) + ")",
+ *this, 2 );
+ }
+ }
+ return bRet;
+}
+
+
+void Statement::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,const Any& rValue )
+{
+ m_props[nHandle] = rValue;
+}
+
+void Statement::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ rValue = m_props[nHandle];
+}
+
+Reference < XPropertySetInfo > Statement::getPropertySetInfo()
+{
+ return OPropertySetHelper::createPropertySetInfo( getStatementPropertyArrayHelper() );
+}
+
+
+Reference< XResultSet > Statement::getResultSet( )
+{
+ return Reference< XResultSet > ( m_lastResultset, css::uno::UNO_QUERY );
+}
+
+sal_Int32 Statement::getUpdateCount( )
+{
+ return m_multipleResultUpdateCount;
+}
+
+sal_Bool Statement::getMoreResults( )
+{
+ // The PostgreSQL C interface always returns a single result,
+ // so we will never have multiple ones.
+ // Implicitly close the open resultset (if any) as per spec,
+ // and setup to signal "no more result, neither as resultset,
+ // nor as update count".
+ Reference< XCloseable > lastResultSetHolder = m_lastResultset;
+ if( lastResultSetHolder.is() )
+ lastResultSetHolder->close();
+ m_multipleResultUpdateCount = -1;
+ return false;
+}
+
+
+void Statement::disposing()
+{
+ close();
+}
+
+Reference< XResultSet > Statement::getGeneratedValues( )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ return getGeneratedValuesFromLastInsert(
+ m_pSettings, m_connection, m_lastOidInserted, m_lastTableInserted, m_lastQuery );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_statement.hxx b/connectivity/source/drivers/postgresql/pq_statement.hxx
new file mode 100644
index 000000000..fae6568bb
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_statement.hxx
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/component.hxx>
+
+#include <libpq-fe.h>
+
+#include "pq_connection.hxx"
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+#include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+
+namespace pq_sdbc_driver
+{
+
+const sal_Int32 STATEMENT_CURSOR_NAME = 0;
+const sal_Int32 STATEMENT_ESCAPE_PROCESSING = 1;
+const sal_Int32 STATEMENT_FETCH_DIRECTION = 2;
+const sal_Int32 STATEMENT_FETCH_SIZE = 3;
+const sal_Int32 STATEMENT_MAX_FIELD_SIZE = 4;
+const sal_Int32 STATEMENT_MAX_ROWS = 5;
+const sal_Int32 STATEMENT_QUERY_TIME_OUT = 6;
+const sal_Int32 STATEMENT_RESULT_SET_CONCURRENCY = 7;
+const sal_Int32 STATEMENT_RESULT_SET_TYPE = 8;
+
+#define STATEMENT_SIZE 9
+
+typedef ::cppu::WeakComponentImplHelper< css::sdbc::XStatement,
+ css::sdbc::XCloseable,
+ css::sdbc::XWarningsSupplier,
+ css::sdbc::XMultipleResults,
+ css::sdbc::XGeneratedResultSet,
+ css::sdbc::XResultSetMetaDataSupplier
+ > Statement_BASE;
+
+class Statement : public Statement_BASE,
+ public cppu::OPropertySetHelper
+{
+private:
+ css::uno::Any m_props[STATEMENT_SIZE];
+ css::uno::Reference< css::sdbc::XConnection > m_connection;
+ ConnectionSettings *m_pSettings;
+ css::uno::Reference< css::sdbc::XCloseable > m_lastResultset;
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ bool m_multipleResultAvailable;
+ sal_Int32 m_multipleResultUpdateCount;
+ sal_Int32 m_lastOidInserted;
+ OUString m_lastTableInserted;
+ OString m_lastQuery;
+
+public:
+ /**
+ * @param ppConnection The piece of memory, pConnection points to, is accessible
+ * as long as a reference to parameter con is held.
+ */
+ Statement( const rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection> & con,
+ struct ConnectionSettings *pSettings );
+
+ virtual ~Statement() override;
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { Statement_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { Statement_BASE::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & reqType ) override;
+
+public: // XCloseable
+ virtual void SAL_CALL close( ) override;
+
+public: // XStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery(
+ const OUString& sql ) override;
+ virtual sal_Int32 SAL_CALL executeUpdate( const OUString& sql ) override;
+ virtual sal_Bool SAL_CALL execute( const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+
+public: // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // OPropertySetHelper
+ virtual cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+
+ void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle ) const override;
+
+ // XPropertySet
+ css::uno::Reference < css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+
+public: // XGeneratedResultSet
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL
+ getGeneratedValues( ) override;
+
+public: // XMultipleResults
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet( ) override;
+ virtual sal_Int32 SAL_CALL getUpdateCount( ) override;
+ virtual sal_Bool SAL_CALL getMoreResults( ) override;
+
+public: // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+public: // XResultSetMetaDataSupplier (is required by framework (see
+ // dbaccess/source/core/api/preparedstatement.cxx::getMetaData() )
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+
+private:
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkClosed();
+ /// @throws css::sdbc::SQLException
+ void raiseSQLException( std::u16string_view sql, const char * errorMsg );
+};
+
+
+struct CommandData
+{
+ ConnectionSettings **ppSettings;
+ sal_Int32 *pLastOidInserted;
+ sal_Int32 *pMultipleResultUpdateCount;
+ bool *pMultipleResultAvailable;
+ OUString *pLastTableInserted;
+ css::uno::Reference< css::sdbc::XCloseable > *pLastResultset;
+ OString *pLastQuery;
+ ::rtl::Reference< comphelper::RefCountedMutex > refMutex;
+ css::uno::Reference< css::uno::XInterface > owner;
+ css::uno::Reference< css::sdbcx::XTablesSupplier > tableSupplier;
+ sal_Int32 concurrency;
+};
+
+bool executePostgresCommand( const OString & cmd, struct CommandData *data );
+css::uno::Reference< css::sdbc::XResultSet > getGeneratedValuesFromLastInsert(
+ ConnectionSettings *pConnectionSettings,
+ const css::uno::Reference< css::sdbc::XConnection > &connection,
+ sal_Int32 nLastOid,
+ const OUString & lastTableInserted,
+ const OString & lastQuery );
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_statics.cxx b/connectivity/source/drivers/postgresql/pq_statics.cxx
new file mode 100644
index 000000000..ec3d0d8ac
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_statics.cxx
@@ -0,0 +1,626 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include "pq_statics.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::PropertyAttribute::READONLY;
+using com::sun::star::beans::Property;
+
+namespace pq_sdbc_driver
+{
+
+namespace {
+
+struct DefColumnMetaData
+{
+ const char * columnName;
+ const char * tableName;
+ const char * schemaTableName;
+ const char * typeName;
+ sal_Int32 type;
+ sal_Int32 precision;
+ sal_Int32 scale;
+ bool isCurrency;
+ bool isNullable;
+ bool isAutoIncrement;
+};
+
+struct BaseTypeDef { const char * typeName; sal_Int32 value; };
+
+struct PropertyDef
+{
+ PropertyDef( const OUString &str, const Type &t )
+ : name( str ) , type( t ) {}
+ OUString name;
+ css::uno::Type type;
+};
+
+struct PropertyDefEx : public PropertyDef
+{
+ PropertyDefEx( const OUString & str, const Type &t , sal_Int32 a )
+ : PropertyDef( str, t ) , attribute( a )
+ {}
+ sal_Int32 attribute;
+};
+
+}
+
+static cppu::IPropertyArrayHelper * createPropertyArrayHelper(
+ PropertyDef const *props, int count , sal_Int16 attr )
+{
+ Sequence< Property > seq( count );
+ auto seqRange = asNonConstRange(seq);
+ for( int i = 0 ; i < count ; i ++ )
+ {
+ seqRange[i] = Property( props[i].name, i, props[i].type, attr );
+ }
+ return new cppu::OPropertyArrayHelper( seq, true );
+}
+
+static cppu::IPropertyArrayHelper * createPropertyArrayHelper(
+ PropertyDefEx const *props, int count )
+{
+ Sequence< Property > seq( count );
+ auto seqRange = asNonConstRange(seq);
+ for( int i = 0 ; i < count ; i ++ )
+ {
+ seqRange[i] = Property( props[i].name, i, props[i].type, props[i].attribute );
+ }
+ return new cppu::OPropertyArrayHelper( seq, true );
+}
+
+Statics & getStatics()
+{
+ static Statics* p = []() {
+ static Statics statics ;
+ statics.SYSTEM_TABLE = "SYSTEM TABLE";
+ statics.TABLE = "TABLE";
+ statics.VIEW = "VIEW";
+ statics.UNKNOWN = "UNKNOWN";
+ statics.YES = "YES";
+ statics.NO = "NO";
+ statics.NO_NULLS = "NO_NULLS";
+ statics.NULABLE = "NULABLE";
+ statics.NULLABLE_UNKNOWN = "NULLABLE_UNKNOWN";
+
+ statics.TYPE = "Type";
+ statics.TYPE_NAME = "TypeName";
+ statics.NAME = "Name";
+ statics.SCHEMA_NAME = "SchemaName";
+ statics.CATALOG_NAME = "CatalogName";
+ statics.DESCRIPTION = "Description";
+ statics.PRIVILEGES = "Privileges";
+
+ statics.DEFAULT_VALUE = "DefaultValue";
+ statics.IS_AUTO_INCREMENT = "IsAutoIncrement";
+ statics.IS_CURRENCY = "IsCurrency";
+ statics.IS_NULLABLE = "IsNullable";
+ statics.IS_ROW_VERSISON = "IsRowVersion";
+ statics.PRECISION = "Precision";
+ statics.SCALE = "Scale";
+
+ statics.cPERCENT = "%";
+ statics.BEGIN = "BEGIN";
+ statics.COMMIT = "COMMIT";
+ statics.ROLLBACK = "ROLLBACK";
+
+ statics.KEY = "Key";
+ statics.REFERENCED_TABLE = "ReferencedTable";
+ statics.UPDATE_RULE = "UpdateRule";
+ statics.DELETE_RULE = "DeleteRule";
+ statics.PRIVATE_COLUMNS = "PrivateColumns";
+ statics.PRIVATE_FOREIGN_COLUMNS = "PrivateForeignColumns";
+
+ statics.KEY_COLUMN = "KeyColumn";
+ statics.RELATED_COLUMN = "RelatedColumn";
+ statics.PASSWORD = "Password";
+ statics.USER = "User";
+
+ statics.CURSOR_NAME = "CursorName";
+ statics.ESCAPE_PROCESSING = "EscapeProcessing";
+ statics.FETCH_DIRECTION = "FetchDirection";
+ statics.FETCH_SIZE = "FetchSize";
+ statics.IS_BOOKMARKABLE = "IsBookmarkable";
+ statics.RESULT_SET_CONCURRENCY = "ResultSetConcurrency";
+ statics.RESULT_SET_TYPE = "ResultSetType";
+
+ statics.COMMAND = "Command";
+ statics.CHECK_OPTION = "CheckOption";
+
+ statics.TRUE = "t";
+ statics.FALSE = "f";
+ statics.IS_PRIMARY_KEY_INDEX = "IsPrimaryKeyIndex";
+ statics.IS_CLUSTERED = "IsClustered";
+ statics.IS_UNIQUE = "IsUnique";
+ statics.IS_ASCENDING = "IsAscending";
+ statics.PRIVATE_COLUMN_INDEXES = "PrivateColumnIndexes";
+ statics.HELP_TEXT = "HelpText";
+
+ statics.CATALOG = "Catalog";
+
+ Type tString = cppu::UnoType<OUString>::get();
+ Type tInt = cppu::UnoType<sal_Int32>::get();
+ Type tBool = cppu::UnoType<bool>::get();
+ Type tStringSequence = cppu::UnoType<css::uno::Sequence< OUString >>::get();
+
+ // Table props set
+ ImplementationStatics &ist = statics.refl.table;
+ ist.implName = "org.openoffice.comp.pq.sdbcx.Table";
+ ist.serviceNames = { "com.sun.star.sdbcx.Table" };
+ PropertyDef tableDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.DESCRIPTION , tString ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRIVILEGES , tInt ),
+ PropertyDef( statics.SCHEMA_NAME , tString ),
+ PropertyDef( statics.TYPE , tString )
+ };
+ ist.pProps = createPropertyArrayHelper(
+ tableDef, std::size(tableDef), READONLY );
+
+ statics.refl.tableDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.TableDescriptor";
+ statics.refl.tableDescriptor.serviceNames = { "com.sun.star.sdbcx.TableDescriptor" };
+ PropertyDef tableDescDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.DESCRIPTION , tString ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRIVILEGES , tInt ),
+ PropertyDef( statics.SCHEMA_NAME , tString )
+ };
+ statics.refl.tableDescriptor.pProps = createPropertyArrayHelper(
+ tableDescDef, std::size(tableDescDef), 0 );
+
+ // Column props set
+ statics.refl.column.implName = "org.openoffice.comp.pq.sdbcx.Column";
+ statics.refl.column.serviceNames = { "com.sun.star.sdbcx.Column" };
+ PropertyDefEx columnDef[] =
+ {
+ PropertyDefEx( statics.CATALOG_NAME , tString, READONLY ),
+ PropertyDefEx( statics.DEFAULT_VALUE, tString, READONLY ),
+ PropertyDefEx( statics.DESCRIPTION , tString, READONLY ),
+// PropertyDefEx( statics.HELP_TEXT , tString, BOUND ),
+ PropertyDefEx( statics.IS_AUTO_INCREMENT, tBool, READONLY ),
+ PropertyDefEx( statics.IS_CURRENCY, tBool, READONLY ),
+ PropertyDefEx( statics.IS_NULLABLE, tInt, READONLY ),
+ PropertyDefEx( statics.IS_ROW_VERSISON, tBool,READONLY ),
+ PropertyDefEx( statics.NAME , tString,READONLY ),
+ PropertyDefEx( statics.PRECISION , tInt, READONLY ),
+ PropertyDefEx( statics.SCALE , tInt ,READONLY),
+ PropertyDefEx( statics.TYPE , tInt ,READONLY),
+ PropertyDefEx( statics.TYPE_NAME , tString ,READONLY)
+ };
+ statics.refl.column.pProps = createPropertyArrayHelper(
+ columnDef, std::size(columnDef) );
+
+ statics.refl.columnDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.ColumnDescriptor";
+ statics.refl.columnDescriptor.serviceNames = { "com.sun.star.sdbcx.ColumnDescriptor" };
+ PropertyDef columnDescDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.DEFAULT_VALUE, tString ),
+ PropertyDef( statics.DESCRIPTION , tString ),
+// PropertyDef( statics.HELP_TEXT , tString ),
+ PropertyDef( statics.IS_AUTO_INCREMENT, tBool ),
+ PropertyDef( statics.IS_CURRENCY, tBool ),
+ PropertyDef( statics.IS_NULLABLE, tInt ),
+ PropertyDef( statics.IS_ROW_VERSISON, tBool ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRECISION , tInt ),
+ PropertyDef( statics.SCALE , tInt ),
+ PropertyDef( statics.TYPE , tInt ),
+ PropertyDef( statics.TYPE_NAME , tString )
+ };
+
+ statics.refl.columnDescriptor.pProps = createPropertyArrayHelper(
+ columnDescDef, std::size(columnDescDef), 0 );
+
+ // Key properties
+ statics.refl.key.implName = "org.openoffice.comp.pq.sdbcx.Key";
+ statics.refl.key.serviceNames = { "com.sun.star.sdbcx.Key" };
+ PropertyDef keyDef[] =
+ {
+ PropertyDef( statics.DELETE_RULE, tInt ),
+ PropertyDef( statics.NAME, tString ),
+ PropertyDef( statics.PRIVATE_COLUMNS, tStringSequence ),
+ PropertyDef( statics.PRIVATE_FOREIGN_COLUMNS, tStringSequence ),
+ PropertyDef( statics.REFERENCED_TABLE, tString ),
+ PropertyDef( statics.TYPE, tInt ),
+ PropertyDef( statics.UPDATE_RULE, tInt )
+ };
+ statics.refl.key.pProps = createPropertyArrayHelper(
+ keyDef, std::size(keyDef), READONLY );
+
+
+ // Key properties
+ statics.refl.keyDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.KeyDescriptor";
+ statics.refl.keyDescriptor.serviceNames = { "com.sun.star.sdbcx.KeyDescriptor" };
+ PropertyDef keyDescDef[] =
+ {
+ PropertyDef( statics.DELETE_RULE, tInt ),
+ PropertyDef( statics.NAME, tString ),
+ PropertyDef( statics.REFERENCED_TABLE, tString ),
+ PropertyDef( statics.TYPE, tInt ),
+ PropertyDef( statics.UPDATE_RULE, tInt )
+ };
+ statics.refl.keyDescriptor.pProps = createPropertyArrayHelper(
+ keyDescDef, std::size(keyDescDef), 0 );
+
+
+ // KeyColumn props set
+ statics.refl.keycolumn.implName = "org.openoffice.comp.pq.sdbcx.KeyColumn";
+ statics.refl.keycolumn.serviceNames = { "com.sun.star.sdbcx.KeyColumn" };
+ PropertyDef keycolumnDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.DEFAULT_VALUE, tString ),
+ PropertyDef( statics.DESCRIPTION , tString ),
+ PropertyDef( statics.IS_AUTO_INCREMENT, tBool ),
+ PropertyDef( statics.IS_CURRENCY, tBool ),
+ PropertyDef( statics.IS_NULLABLE, tInt ),
+ PropertyDef( statics.IS_ROW_VERSISON, tBool ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRECISION , tInt ),
+ PropertyDef( statics.RELATED_COLUMN, tString ),
+ PropertyDef( statics.SCALE , tInt ),
+ PropertyDef( statics.TYPE , tInt ),
+ PropertyDef( statics.TYPE_NAME , tString )
+ };
+ statics.refl.keycolumn.pProps = createPropertyArrayHelper(
+ keycolumnDef, std::size(keycolumnDef), READONLY );
+
+ // KeyColumn props set
+ statics.refl.keycolumnDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.KeyColumnDescriptor";
+ statics.refl.keycolumnDescriptor.serviceNames =
+ { "com.sun.star.sdbcx.KeyColumnDescriptor" };
+ PropertyDef keycolumnDescDef[] =
+ {
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.RELATED_COLUMN, tString )
+ };
+ statics.refl.keycolumnDescriptor.pProps = createPropertyArrayHelper(
+ keycolumnDescDef, std::size(keycolumnDescDef), 0 );
+
+ // view props set
+ statics.refl.view.implName = "org.openoffice.comp.pq.sdbcx.View";
+ statics.refl.view.serviceNames = { "com.sun.star.sdbcx.View" };
+ PropertyDef viewDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.CHECK_OPTION , tInt ),
+ PropertyDef( statics.COMMAND , tString ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.SCHEMA_NAME , tString )
+ };
+ statics.refl.view.pProps = createPropertyArrayHelper(
+ viewDef, std::size(viewDef), READONLY );
+
+ // view props set
+ statics.refl.viewDescriptor.implName = "org.openoffice.comp.pq.sdbcx.ViewDescriptor";
+ statics.refl.viewDescriptor.serviceNames = { "com.sun.star.sdbcx.ViewDescriptor" };
+ statics.refl.viewDescriptor.pProps = createPropertyArrayHelper(
+ viewDef, std::size(viewDef), 0 ); // reuse view, as it is identical
+ // user props set
+ statics.refl.user.implName = "org.openoffice.comp.pq.sdbcx.User";
+ statics.refl.user.serviceNames = { "com.sun.star.sdbcx.User" };
+ PropertyDef userDefRO[] =
+ {
+ PropertyDef( statics.NAME , tString )
+ };
+ statics.refl.user.pProps = createPropertyArrayHelper(
+ userDefRO, std::size(userDefRO), READONLY );
+
+ // user props set
+ statics.refl.userDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.UserDescriptor";
+ statics.refl.userDescriptor.serviceNames = { "com.sun.star.sdbcx.UserDescriptor" };
+ PropertyDef userDefWR[] =
+ {
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PASSWORD , tString )
+ };
+ statics.refl.userDescriptor.pProps = createPropertyArrayHelper(
+ userDefWR, std::size(userDefWR), 0 );
+
+ // index props set
+ statics.refl.index.implName = "org.openoffice.comp.pq.sdbcx.Index";
+ statics.refl.index.serviceNames = { "com.sun.star.sdbcx.Index" };
+ PropertyDef indexDef[] =
+ {
+ PropertyDef( statics.CATALOG , tString ),
+ PropertyDef( statics.IS_CLUSTERED, tBool ),
+ PropertyDef( statics.IS_PRIMARY_KEY_INDEX, tBool ),
+ PropertyDef( statics.IS_UNIQUE, tBool ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRIVATE_COLUMN_INDEXES, tStringSequence )
+ };
+ statics.refl.index.pProps = createPropertyArrayHelper(
+ indexDef, std::size(indexDef), READONLY );
+
+ // index props set
+ statics.refl.indexDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.IndexDescriptor";
+ statics.refl.indexDescriptor.serviceNames = { "com.sun.star.sdbcx.IndexDescriptor" };
+ statics.refl.indexDescriptor.pProps = createPropertyArrayHelper(
+ indexDef, std::size(indexDef), 0 );
+
+ // indexColumn props set
+ statics.refl.indexColumn.implName = "org.openoffice.comp.pq.sdbcx.IndexColumn";
+ statics.refl.indexColumn.serviceNames = { "com.sun.star.sdbcx.IndexColumn" };
+ PropertyDef indexColumnDef[] =
+ {
+ PropertyDef( statics.CATALOG_NAME , tString ),
+ PropertyDef( statics.DEFAULT_VALUE, tString ),
+ PropertyDef( statics.DESCRIPTION , tString ),
+ PropertyDef( statics.IS_ASCENDING, tBool ),
+ PropertyDef( statics.IS_AUTO_INCREMENT, tBool ),
+ PropertyDef( statics.IS_CURRENCY, tBool ),
+ PropertyDef( statics.IS_NULLABLE, tInt ),
+ PropertyDef( statics.IS_ROW_VERSISON, tBool ),
+ PropertyDef( statics.NAME , tString ),
+ PropertyDef( statics.PRECISION , tInt ),
+ PropertyDef( statics.SCALE , tInt ),
+ PropertyDef( statics.TYPE , tInt ),
+ PropertyDef( statics.TYPE_NAME , tString )
+ };
+ statics.refl.indexColumn.pProps = createPropertyArrayHelper(
+ indexColumnDef, std::size(indexColumnDef), READONLY );
+
+ // indexColumn props set
+ statics.refl.indexColumnDescriptor.implName =
+ "org.openoffice.comp.pq.sdbcx.IndexColumnDescriptor";
+ statics.refl.indexColumnDescriptor.serviceNames =
+ { "com.sun.star.sdbcx.IndexColumnDescriptor" };
+ PropertyDef indexColumnDescDef[] =
+ {
+ PropertyDef( statics.IS_ASCENDING, tBool ),
+ PropertyDef( statics.NAME , tString )
+ };
+ statics.refl.indexColumnDescriptor.pProps = createPropertyArrayHelper(
+ indexColumnDescDef, std::size(indexColumnDescDef), 0 );
+
+ // databasemetadata
+ statics.tablesRowNames = std::vector< OUString > ( 5 );
+ statics.tablesRowNames[TABLE_INDEX_CATALOG] = "TABLE_CAT";
+ statics.tablesRowNames[TABLE_INDEX_SCHEMA] = "TABLE_SCHEM";
+ statics.tablesRowNames[TABLE_INDEX_NAME] = "TABLE_NAME";
+ statics.tablesRowNames[TABLE_INDEX_TYPE] = "TABLE_TYPE";
+ statics.tablesRowNames[TABLE_INDEX_REMARKS] = "REMARKS";
+
+ statics.primaryKeyNames = std::vector< OUString > ( 6 );
+ statics.primaryKeyNames[0] = "TABLE_CAT";
+ statics.primaryKeyNames[1] = "TABLE_SCHEM";
+ statics.primaryKeyNames[2] = "TABLE_NAME";
+ statics.primaryKeyNames[3] = "COLUMN_NAME";
+ statics.primaryKeyNames[4] = "KEY_SEQ";
+ statics.primaryKeyNames[5] = "PK_NAME";
+
+ statics.SELECT = "SELECT";
+ statics.UPDATE = "UPDATE";
+ statics.INSERT = "INSERT";
+ statics.DELETE = "DELETE";
+ statics.RULE = "RULE";
+ statics.REFERENCES = "REFERENCES";
+ statics.TRIGGER = "TRIGGER";
+ statics.EXECUTE = "EXECUTE";
+ statics.USAGE = "USAGE";
+ statics.CREATE = "CREATE";
+ statics.TEMPORARY = "TEMPORARY";
+ statics.INDEX = "Index";
+ statics.INDEX_COLUMN = "IndexColumn";
+
+ statics.schemaNames = std::vector< OUString > ( 1 );
+ statics.schemaNames[0] = "TABLE_SCHEM";
+
+ statics.tableTypeData = std::vector< std::vector< Any > >( 2 );
+
+ statics.tableTypeData[0] = std::vector< Any > ( 1 );
+ statics.tableTypeData[0][0] <<= statics.TABLE;
+
+// statics.tableTypeData[2] = Sequence< Any > ( 1 );
+// statics.tableTypeData[2][0] <<= statics.VIEW;
+
+ statics.tableTypeData[1] = std::vector< Any > ( 1 );
+ statics.tableTypeData[1][0] <<= statics.SYSTEM_TABLE;
+
+ statics.tableTypeNames = std::vector< OUString > ( 1 );
+ statics.tableTypeNames[0] = "TABLE_TYPE";
+
+ statics.columnRowNames =
+ {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME",
+ "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
+ "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH",
+ "ORDINAL_POSITION", "IS_NULLABLE"
+ };
+
+ statics.typeinfoColumnNames =
+ {
+ "TYPE_NAME", "DATA_TYPE", "PRECISION", "LITERAL_PREFIX",
+ "LITERAL_SUFFIX", "CREATE_PARAMS", "NULLABLE", "CASE_SENSITIVE",
+ "SEARCHABLE", "UNSIGNED_ATTRIBUTE", "FIXED_PREC_SCALE",
+ "AUTO_INCREMENT", "LOCAL_TYPE_NAME", "MINIMUM_SCALE",
+ "MAXIMUM_SCALE", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
+ "NUM_PREC_RADIX"
+ };
+
+ statics.indexinfoColumnNames =
+ {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME",
+ "TYPE", "ORDINAL_POSITION", "COLUMN_NAME",
+ "ASC_OR_DESC", "CARDINALITY", "PAGES", "FILTER_CONDITION"
+ };
+
+ statics.resultSetArrayColumnNames = { "INDEX" , "VALUE" };
+
+ // LEM TODO see if a refresh is needed; obtain automatically from pg_catalog.pg_type?
+ BaseTypeDef baseTypeDefs[] =
+ {
+ { "bool" , css::sdbc::DataType::BOOLEAN },
+ { "bytea", css::sdbc::DataType::VARBINARY },
+ { "char" , css::sdbc::DataType::CHAR },
+
+ { "int8" , css::sdbc::DataType::BIGINT },
+ { "serial8" , css::sdbc::DataType::BIGINT },
+
+
+ { "int2" , css::sdbc::DataType::SMALLINT },
+
+ { "int4" , css::sdbc::DataType::INTEGER },
+// { "regproc" , css::sdbc::DataType::INTEGER },
+// { "oid" , css::sdbc::DataType::INTEGER },
+// { "xid" , css::sdbc::DataType::INTEGER },
+// { "cid" , css::sdbc::DataType::INTEGER },
+// { "serial", css::sdbc::DataType::INTEGER },
+// { "serial4", css::sdbc::DataType::INTEGER },
+
+ { "text", css::sdbc::DataType::LONGVARCHAR },
+ { "bpchar", css::sdbc::DataType::CHAR },
+ { "varchar", css::sdbc::DataType::VARCHAR },
+
+ { "float4", css::sdbc::DataType::REAL },
+ { "float8", css::sdbc::DataType::DOUBLE },
+
+ { "numeric", css::sdbc::DataType::NUMERIC },
+ { "decimal", css::sdbc::DataType::DECIMAL },
+
+ { "date", css::sdbc::DataType::DATE },
+ { "time", css::sdbc::DataType::TIME },
+ { "timestamp", css::sdbc::DataType::TIMESTAMP },
+
+// { "_bool" , css::sdbc::DataType::ARRAY },
+// { "_bytea", css::sdbc::DataType::ARRAY },
+// { "_char" , css::sdbc::DataType::ARRAY },
+
+// { "_int8" , css::sdbc::DataType::ARRAY },
+// { "_serial8" , css::sdbc::DataType::ARRAY },
+
+
+// { "_int2" , css::sdbc::DataType::ARRAY },
+
+// { "_int4" , css::sdbc::DataType::ARRAY },
+// { "_regproc" , css::sdbc::DataType::ARRAY },
+// { "_oid" , css::sdbc::DataType::ARRAY },
+// { "_xid" , css::sdbc::DataType::ARRAY },
+// { "_cid" , css::sdbc::DataType::ARRAY },
+
+// { "_text", css::sdbc::DataType::ARRAY },
+// { "_bpchar", css::sdbc::DataType::ARRAY },
+// { "_varchar", css::sdbc::DataType::ARRAY },
+
+// { "_float4", css::sdbc::DataType::ARRAY },
+// { "_float8", css::sdbc::DataType::ARRAY },
+
+// { "_numeric", css::sdbc::DataType::ARRAY },
+// { "_decimal", css::sdbc::DataType::ARRAY },
+
+// { "_date", css::sdbc::DataType::ARRAY }, // switch to date later
+// { "_time", css::sdbc::DataType::ARRAY }, // switch to time later
+
+ { nullptr, 0 }
+ };
+ int i;
+ for( i = 0 ; baseTypeDefs[i].typeName ; i ++ )
+ {
+ statics.baseTypeMap[
+ OUString::createFromAscii( baseTypeDefs[i].typeName) ] =
+ baseTypeDefs[i].value;
+ }
+
+ // This is the metadata for the columns of the recordset returned
+ // by css::sdbc::XDatabaseMetaData::getTypeInfo(),
+ // that is what is returned by getTypeInfo().getMetaData()
+ DefColumnMetaData defTypeInfoMetaData[] =
+ {
+ { "TYPE_NAME", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::VARCHAR, 0,50,false,false,false }, // 0
+ { "DATA_TYPE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::SMALLINT, 0,50,false,false,false }, // 1
+ { "PRECISION", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::INTEGER, 0,50,false,false,false }, // 2
+ { "LITERAL_PREFIX", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::VARCHAR, 0,50,false,false,false }, // 3
+ { "LITERAL_SUFFIX", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::VARCHAR, 0,50,false,false,false }, // 4
+ { "CREATE_PARAMS", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::VARCHAR, 0,50,false,false,false }, // 5
+ { "NULLABLE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::INTEGER, 0,50,false,false,false }, // 6
+ { "CASE_SENSITIVE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::BOOLEAN, 0,50,false,false,false }, // 7
+ { "SEARCHABLE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::SMALLINT, 0,50,false,false,false }, // 8
+ { "UNSIGNED_ATTRIBUTE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::BOOLEAN, 0,50,false,false,false }, // 9
+ { "FIXED_PREC_SCALE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::BOOLEAN, 0,50,false,false,false }, // 10
+ { "AUTO_INCREMENT", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::BOOLEAN, 0,50,false,false,false }, // 11
+ { "LOCAL_TYPE_NAME", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::VARCHAR, 0,50,false,false,false }, // 12
+ { "MINIMUM_SCALE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::SMALLINT, 0,50,false,false,false}, // 13
+ { "MAXIMUM_SCALE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::SMALLINT, 0,50,false,false,false }, // 14
+ { "SQL_DATA_TYPE", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::INTEGER, 0,50,false,false,false }, // 15
+ { "SQL_DATETIME_SUB", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::INTEGER, 0,50,false,false,false}, // 16
+ { "NUM_PREC_RADIX", "TYPEINFO", "pg_catalog", "", css::sdbc::DataType::INTEGER, 0,50,false,false,false }, // 17
+ {nullptr,nullptr,nullptr,nullptr,0,0,0,false,false,false}
+ };
+
+ for( i = 0 ; defTypeInfoMetaData[i].columnName ; i++ )
+ {
+ statics.typeInfoMetaData.push_back(
+ ColumnMetaData(
+ OUString::createFromAscii( defTypeInfoMetaData[i].columnName ),
+ OUString::createFromAscii( defTypeInfoMetaData[i].tableName ),
+ OUString::createFromAscii( defTypeInfoMetaData[i].schemaTableName ),
+ OUString::createFromAscii( defTypeInfoMetaData[i].typeName ),
+ defTypeInfoMetaData[i].type,
+ defTypeInfoMetaData[i].precision,
+ defTypeInfoMetaData[i].scale,
+ defTypeInfoMetaData[i].isCurrency,
+ defTypeInfoMetaData[i].isNullable,
+ defTypeInfoMetaData[i].isAutoIncrement ) );
+ }
+
+ return &statics;
+ }();
+ return *p;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_statics.hxx b/connectivity/source/drivers/postgresql/pq_statics.hxx
new file mode 100644
index 000000000..b5a868d6c
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_statics.hxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <unordered_map>
+#include <vector>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <cppuhelper/propshlp.hxx>
+
+namespace pq_sdbc_driver
+{
+
+struct ColumnMetaData
+{
+ ColumnMetaData(
+ const OUString &_columnName,
+ const OUString &_tableName,
+ const OUString &_schemaTableName,
+ const OUString &_typeName,
+ sal_Int32 _type,
+ sal_Int32 _precision,
+ sal_Int32 _scale,
+ bool _isCurrency,
+ bool _isNullable,
+ bool _isAutoIncrement ) :
+ columnName( _columnName ),
+ tableName( _tableName ),
+ schemaTableName( _schemaTableName ),
+ typeName( _typeName ),
+ type( _type ),
+ precision( _precision ),
+ scale( _scale ),
+ isCurrency( _isCurrency ),
+ isNullable( _isNullable ),
+ isAutoIncrement( _isAutoIncrement )
+ {}
+
+ OUString columnName;
+ OUString tableName;
+ OUString schemaTableName;
+ OUString typeName;
+ sal_Int32 type;
+ sal_Int32 precision;
+ sal_Int32 scale;
+ bool isCurrency;
+ bool isNullable;
+ bool isAutoIncrement;
+};
+
+typedef std::vector< ColumnMetaData > ColumnMetaDataVector;
+
+typedef std::unordered_map
+<
+ OUString,
+ sal_Int32
+> BaseTypeMap;
+
+struct ImplementationStatics
+{
+ ImplementationStatics() :
+ pProps(nullptr)
+ {}
+
+ OUString implName;
+ css::uno::Sequence< OUString > serviceNames;
+ cppu::IPropertyArrayHelper *pProps;
+ css::uno::Sequence< css::uno::Type > types;
+};
+
+struct ReflectionImplementations
+{
+ struct ImplementationStatics table;
+ struct ImplementationStatics tableDescriptor;
+ struct ImplementationStatics column;
+ struct ImplementationStatics columnDescriptor;
+ struct ImplementationStatics key;
+ struct ImplementationStatics keyDescriptor;
+ struct ImplementationStatics keycolumn;
+ struct ImplementationStatics keycolumnDescriptor;
+ struct ImplementationStatics user;
+ struct ImplementationStatics userDescriptor;
+ struct ImplementationStatics view;
+ struct ImplementationStatics viewDescriptor;
+ struct ImplementationStatics index;
+ struct ImplementationStatics indexDescriptor;
+ struct ImplementationStatics indexColumn;
+ struct ImplementationStatics indexColumnDescriptor;
+};
+
+const sal_Int32 TABLE_INDEX_CATALOG = 0;
+const sal_Int32 TABLE_INDEX_SCHEMA = 1;
+const sal_Int32 TABLE_INDEX_NAME = 2;
+const sal_Int32 TABLE_INDEX_TYPE = 3;
+const sal_Int32 TABLE_INDEX_REMARKS = 4;
+
+struct Statics
+{
+ OUString SYSTEM_TABLE;
+ OUString TABLE;
+ OUString VIEW;
+ OUString UNKNOWN;
+ OUString YES;
+ OUString NO;
+ OUString NO_NULLS;
+ OUString NULABLE;
+ OUString NULLABLE_UNKNOWN;
+ OUString SELECT;
+ OUString UPDATE;
+ OUString INSERT;
+ OUString DELETE;
+ OUString RULE;
+ OUString REFERENCES;
+ OUString TRIGGER;
+ OUString EXECUTE;
+ OUString USAGE;
+ OUString CREATE;
+ OUString TEMPORARY;
+ OUString INDEX;
+ OUString INDEX_COLUMN;
+
+ OUString NAME;
+ OUString SCHEMA_NAME;
+ OUString CATALOG_NAME;
+ OUString DESCRIPTION;
+ OUString TYPE;
+ OUString TYPE_NAME;
+ OUString PRIVILEGES;
+
+ OUString DEFAULT_VALUE;
+ OUString IS_AUTO_INCREMENT;
+ OUString IS_CURRENCY;
+ OUString IS_NULLABLE;
+ OUString IS_ROW_VERSISON;
+ OUString PRECISION;
+ OUString SCALE;
+
+ OUString cPERCENT;
+
+ OUString BEGIN;
+ OUString ROLLBACK;
+ OUString COMMIT;
+
+ OUString KEY;
+ OUString REFERENCED_TABLE;
+ OUString UPDATE_RULE;
+ OUString DELETE_RULE;
+ OUString PRIVATE_COLUMNS;
+ OUString PRIVATE_FOREIGN_COLUMNS;
+
+ OUString KEY_COLUMN;
+ OUString RELATED_COLUMN;
+
+ OUString PASSWORD;
+ OUString USER;
+
+ OUString CURSOR_NAME;
+ OUString ESCAPE_PROCESSING;
+ OUString FETCH_DIRECTION;
+ OUString FETCH_SIZE;
+ OUString IS_BOOKMARKABLE;
+ OUString RESULT_SET_CONCURRENCY;
+ OUString RESULT_SET_TYPE;
+
+ OUString COMMAND;
+ OUString CHECK_OPTION;
+
+ OUString TRUE;
+ OUString FALSE;
+
+ OUString IS_PRIMARY_KEY_INDEX;
+ OUString IS_CLUSTERED;
+ OUString IS_UNIQUE;
+ OUString PRIVATE_COLUMN_INDEXES;
+ OUString HELP_TEXT;
+
+ OUString CATALOG;
+ OUString IS_ASCENDING;
+ ReflectionImplementations refl;
+
+ std::vector< OUString > tablesRowNames;
+ std::vector< OUString > columnRowNames;
+ std::vector< OUString > primaryKeyNames;
+ std::vector< OUString > schemaNames;
+ std::vector< OUString > tableTypeNames;
+ std::vector< OUString > typeinfoColumnNames;
+ std::vector< OUString > indexinfoColumnNames;
+ std::vector< OUString > resultSetArrayColumnNames;
+ std::vector< std::vector< css::uno::Any > > tableTypeData;
+
+ ColumnMetaDataVector typeInfoMetaData;
+ BaseTypeMap baseTypeMap;
+ Statics(){}
+private:
+ Statics( const Statics & ) = delete;
+ Statics & operator = ( const Statics & ) = delete;
+};
+
+Statics & getStatics();
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_tools.cxx b/connectivity/source/drivers/postgresql/pq_tools.cxx
new file mode 100644
index 000000000..eb90c24ce
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_tools.cxx
@@ -0,0 +1,1249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <o3tl/string_view.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/KeyRule.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+#include <libpq-fe.h>
+#include <string.h>
+#include <string_view>
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::lang::XComponent;
+
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XConnection;
+using com::sun::star::sdbc::XPreparedStatement;
+using com::sun::star::sdbc::XParameters;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XRow;
+
+using com::sun::star::sdbcx::XColumnsSupplier;
+
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::Any;
+
+using com::sun::star::container::XEnumeration;
+using com::sun::star::container::XEnumerationAccess;
+
+namespace pq_sdbc_driver
+{
+
+OUString concatQualified( std::u16string_view a, std::u16string_view b)
+{
+ return OUString::Concat(a) + "." + b;
+}
+
+static OString iOUStringToOString( std::u16string_view str, ConnectionSettings const *settings) {
+ OSL_ENSURE(settings, "pgsql-sdbc: OUStringToOString got NULL settings");
+ return rtl::OUStringToOString( str, ConnectionSettings::encoding );
+}
+
+OString OUStringToOString( std::u16string_view str, ConnectionSettings const *settings) {
+ return iOUStringToOString( str, settings );
+}
+
+void bufferEscapeConstant( OUStringBuffer & buf, std::u16string_view value, ConnectionSettings *settings )
+{
+
+ OString y = iOUStringToOString( value, settings );
+ OStringBuffer strbuf( y.getLength() * 2 + 2 );
+ int error;
+ int len = PQescapeStringConn(settings->pConnection, const_cast<char*>(strbuf.getStr()), y.getStr() , y.getLength(), &error );
+ if ( error )
+ {
+ char *errstr = PQerrorMessage(settings->pConnection);
+ // As of PostgreSQL 9.1, the only possible errors "involve invalid multibyte encoding"
+ // According to https://www2.opengroup.org/ogsys/jsp/publications/PublicationDetails.jsp?publicationid=11216
+ // (X/Open SQL CLI, March 1995, ISBN: 1-85912-081-4, X/Open Document Number: C451)
+ // 22018 is for "Invalid character value" and seems to be the best match.
+ // We have no good XInterface Reference to pass here, so just give NULL
+ throw SQLException(OUString(errstr, strlen(errstr), ConnectionSettings::encoding),
+ nullptr,
+ "22018",
+ -1,
+ Any());
+ }
+ strbuf.setLength( len );
+ // Previously here RTL_TEXTENCODING_ASCII_US; as we set the PostgreSQL client_encoding to UTF8,
+ // we get UTF8 here, too. I'm not sure why it worked well before...
+ buf.append( OStringToOUString( strbuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) );
+}
+
+static void ibufferQuoteConstant( OUStringBuffer & buf, std::u16string_view value, ConnectionSettings *settings )
+{
+ buf.append( "'" );
+ bufferEscapeConstant( buf, value, settings );
+ buf.append( "'" );
+}
+
+void bufferQuoteConstant( OUStringBuffer & buf, std::u16string_view value, ConnectionSettings *settings )
+{
+ return ibufferQuoteConstant( buf, value, settings );
+}
+
+void bufferQuoteAnyConstant( OUStringBuffer & buf, const Any &val, ConnectionSettings *settings )
+{
+ if( val.hasValue() )
+ {
+ OUString str;
+ val >>= str;
+ bufferQuoteConstant( buf, str, settings );
+ }
+ else
+ buf.append( "NULL" );
+}
+
+static void ibufferQuoteIdentifier( OUStringBuffer & buf, std::u16string_view toQuote, ConnectionSettings *settings )
+{
+ OSL_ENSURE(settings, "pgsql-sdbc: bufferQuoteIdentifier got NULL settings");
+
+ OString y = iOUStringToOString( toQuote, settings );
+ char *cstr = PQescapeIdentifier(settings->pConnection, y.getStr(), y.getLength());
+ if ( cstr == nullptr )
+ {
+ char *errstr = PQerrorMessage(settings->pConnection);
+ // Implementation-defined SQLACCESS error
+ throw SQLException(OUString(errstr, strlen(errstr), ConnectionSettings::encoding),
+ nullptr,
+ "22018",
+ -1,
+ Any());
+ }
+ buf.append( OStringToOUString( cstr, RTL_TEXTENCODING_UTF8 ) );
+ PQfreemem( cstr );
+}
+
+void bufferQuoteIdentifier( OUStringBuffer & buf, std::u16string_view toQuote, ConnectionSettings *settings )
+{
+ return ibufferQuoteIdentifier(buf, toQuote, settings);
+}
+
+
+void bufferQuoteQualifiedIdentifier(
+ OUStringBuffer & buf, std::u16string_view schema, std::u16string_view table, ConnectionSettings *settings )
+{
+ ibufferQuoteIdentifier(buf, schema, settings);
+ buf.append( "." );
+ ibufferQuoteIdentifier(buf, table, settings);
+}
+
+void bufferQuoteQualifiedIdentifier(
+ OUStringBuffer & buf,
+ std::u16string_view schema,
+ std::u16string_view table,
+ std::u16string_view col,
+ ConnectionSettings *settings)
+{
+ ibufferQuoteIdentifier(buf, schema, settings);
+ buf.append( "." );
+ ibufferQuoteIdentifier(buf, table, settings);
+ buf.append( "." );
+ ibufferQuoteIdentifier(buf, col, settings);
+}
+
+
+OUString extractStringProperty(
+ const Reference< XPropertySet > & descriptor, const OUString &name )
+{
+ OUString value;
+ descriptor->getPropertyValue( name ) >>= value;
+ return value;
+}
+
+bool extractBoolProperty(
+ const Reference< XPropertySet > & descriptor, const OUString &name )
+{
+ bool value = false;
+ descriptor->getPropertyValue( name ) >>= value;
+ return value;
+}
+
+sal_Int32 extractIntProperty(
+ const Reference< XPropertySet > & descriptor, const OUString &name )
+{
+ sal_Int32 ret = 0;
+ descriptor->getPropertyValue( name ) >>= ret;
+ return ret;
+}
+
+void disposeObject( const css::uno::Reference< css::uno::XInterface > & r )
+{
+ Reference< XComponent > comp( r, UNO_QUERY );
+ if( comp.is() )
+ comp->dispose();
+}
+
+void disposeNoThrow( const css::uno::Reference< css::uno::XInterface > & r )
+{
+ try
+ {
+ disposeObject( r );
+ }
+ catch( SQLException & )
+ {
+ // ignore this
+ }
+
+}
+
+Reference< XConnection > extractConnectionFromStatement( const Reference< XInterface > & stmt )
+{
+ Reference< XConnection > ret;
+
+ Reference< css::sdbc::XStatement > owner( stmt, UNO_QUERY );
+ if( owner.is() )
+ ret = owner->getConnection();
+ else
+ {
+ Reference< css::sdbc::XPreparedStatement > myowner( stmt, UNO_QUERY );
+ if( myowner.is() )
+ ret = myowner->getConnection();
+ if( ! ret.is() )
+ throw SQLException(
+ "PQSDBC: Couldn't retrieve connection from statement",
+ Reference< XInterface > () , OUString(), 0 , css::uno::Any() );
+ }
+
+ return ret;
+
+}
+
+DisposeGuard::DisposeGuard( const Reference< XInterface > & r )
+ : d( r )
+{}
+
+DisposeGuard::~DisposeGuard()
+{
+ disposeNoThrow( d );
+}
+
+TransactionGuard::TransactionGuard( const Reference< XStatement > &stmt )
+ : m_stmt( stmt ),
+ m_commited( false )
+{
+ m_stmt->executeUpdate( getStatics().BEGIN );
+}
+
+void TransactionGuard::commit()
+{
+ m_stmt->executeUpdate( getStatics().COMMIT );
+ m_commited = true;
+}
+
+void TransactionGuard::executeUpdate( const OUString & sql )
+{
+ m_stmt->executeUpdate( sql );
+}
+
+TransactionGuard::~TransactionGuard()
+{
+ try
+ {
+ if( ! m_commited )
+ m_stmt->executeUpdate( getStatics().ROLLBACK );
+ }
+ catch( css::uno::Exception & )
+ {
+ // ignore, we are within a dtor
+ }
+
+ disposeNoThrow( m_stmt );
+}
+
+
+bool isWhitespace( sal_Unicode c )
+{
+ return ' ' == c || 9 == c || 10 == c || 13 == c;
+}
+
+OUString extractTableFromInsert( const OUString & sql )
+{
+ OUString ret;
+ int i = 0;
+ while (i < sql.getLength() && isWhitespace(sql[i])) { i++; }
+
+ if( sql.matchIgnoreAsciiCase("insert", i) )
+ {
+ i += 6;
+ while (i < sql.getLength() && isWhitespace(sql[i])) { i++; }
+ if( sql.matchIgnoreAsciiCase("into", i) )
+ {
+ i +=4;
+ while (i < sql.getLength() && isWhitespace(sql[i])) { i++; }
+ int start = i;
+ bool quote = (sql[i] == '"');
+ for( i++ ; i < sql.getLength() ; i ++ )
+ {
+ if( quote && sql[i] == '"' )
+ {
+ while (i < sql.getLength() && isWhitespace(sql[i])) { i++; }
+ if( '.' == sql[i] )
+ {
+ while (i < sql.getLength() && isWhitespace(sql[i])) { i++; }
+ if( '"' == sql[i] )
+ {
+ // the second part of the table name does not use quotes
+ // parse on
+ quote = false;
+ }
+ }
+ else
+ {
+ // end quoted name, ok
+ break;
+ }
+ }
+ else
+ {
+ if( isWhitespace( sql[i] ) )
+ {
+ // found the end of an unquoted name
+ break;
+ }
+ }
+ }
+ ret = o3tl::trim(sql.subView(start, i - start ));
+// printf( "pq_statement: parsed table name %s from insert\n" ,
+// OUStringToOString( ret, RTL_TEXTENCODING_ASCII_US).getStr() );
+ }
+ }
+ return ret;
+}
+
+
+static bool isOperator( char c )
+{
+ bool ret;
+ switch(c)
+ {
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '<':
+ case '>':
+ case '=':
+ case '~':
+ case '!':
+ case '@':
+ case '#':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '`':
+ case '?':
+ case '$':
+ ret = true;
+ break;
+ default:
+ ret = false;
+ }
+ return ret;
+}
+
+void splitSQL( const OString & sql, std::vector< OString > &vec )
+{
+ int length = sql.getLength();
+
+ int i = 0;
+ bool singleQuote = false;
+ bool doubleQuote = false;
+ int start = 0;
+ for( ; i < length ; i ++ )
+ {
+ char c = sql[i];
+ if( doubleQuote )
+ {
+ if( '"' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i-start+1 ) );
+ start = i + 1;
+ doubleQuote = false;
+ }
+ }
+ else if( singleQuote )
+ {
+ if( '\'' == c && (i+1) < length && '\'' == sql[i+1] )
+ {
+ // two subsequent single quotes within a quoted string
+ // mean a single quote within the string
+ i ++;
+ }
+ else if( '\'' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i - start +1 ) );
+ start = i + 1; // leave single quotes !
+ singleQuote = false;
+ }
+ }
+ else
+ {
+ if( '"' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i - start ) );
+ doubleQuote = true;
+ start = i;
+ }
+ else if( '\'' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i - start ) );
+ singleQuote = true;
+ start = i;
+ }
+ }
+ }
+ if( start < i )
+ vec.push_back( OString( &sql.getStr()[start] , i - start ) );
+
+// for( i = 0 ; i < vec.size() ; i ++ )
+// printf( "%s!" , vec[i].getStr() );
+// printf( "\n" );
+
+}
+
+void tokenizeSQL( const OString & sql, std::vector< OString > &vec )
+{
+ int length = sql.getLength();
+
+ int i = 0;
+ bool singleQuote = false;
+ bool doubleQuote = false;
+ int start = 0;
+ for( ; i < length ; i ++ )
+ {
+ char c = sql[i];
+ if( doubleQuote )
+ {
+ if( '"' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i-start ) );
+ start = i + 1;
+ doubleQuote = false;
+ }
+ }
+ else if( singleQuote )
+ {
+ if( '\'' == c )
+ {
+ vec.push_back( OString( &sql.getStr()[start], i - start +1 ) );
+ start = i + 1; // leave single quotes !
+ singleQuote = false;
+ }
+ }
+ else
+ {
+ if( '"' == c )
+ {
+ doubleQuote = true;
+ start = i +1; // skip double quotes !
+ }
+ else if( '\'' == c )
+ {
+ singleQuote = true;
+ start = i; // leave single quotes
+ }
+ else if( isWhitespace( c ) )
+ {
+ if( i == start )
+ start ++; // skip additional whitespace
+ else
+ {
+ vec.push_back( OString( &sql.getStr()[start], i - start ) );
+ start = i +1;
+ }
+ }
+ else if( ',' == c || isOperator( c ) || '(' == c || ')' == c )
+ {
+ if( i - start )
+ vec.push_back( OString( &sql.getStr()[start], i - start ) );
+ vec.push_back( OString( &sql.getStr()[i], 1 ) );
+ start = i + 1;
+ }
+ else if( '.' == c )
+ {
+ if( ( i > start && sql[start] >= '0' && sql[start] <= '9' ) ||
+ ( i == start && i > 1 && isWhitespace( sql[i-1] ) ) )
+ {
+ // ignore, is a literal
+ }
+ else
+ {
+ if( i - start )
+ vec.push_back( OString( &sql.getStr()[start], i - start ) );
+ vec.push_back( OString( "." ) );
+ start = i + 1;
+ }
+ }
+ }
+ }
+ if( start < i )
+ vec.push_back( OString( &sql.getStr()[start] , i - start ) );
+
+// for( i = 0 ; i < vec.size() ; i ++ )
+// printf( "%s!" , vec[i].getStr() );
+// printf( "\n" );
+}
+
+
+void splitConcatenatedIdentifier( std::u16string_view source, OUString *first, OUString *second)
+{
+ std::vector< OString > vec;
+ tokenizeSQL( rtl::OUStringToOString( source, RTL_TEXTENCODING_UTF8 ), vec );
+ switch (vec.size())
+ {
+ case 1:
+ first->clear();
+ *second = OStringToOUString( vec[0], RTL_TEXTENCODING_UTF8 );
+ break;
+ case 3:
+ *first = OStringToOUString( vec[0], RTL_TEXTENCODING_UTF8 );
+ *second = OStringToOUString( vec[2], RTL_TEXTENCODING_UTF8 );
+ break;
+ default:
+ SAL_WARN("connectivity.postgresql",
+ "pq_tools::splitConcatenatedIdentifier unexpected number of tokens in identifier: "
+ << vec.size());
+ }
+}
+
+OUString array2String( const css::uno::Sequence< Any > &seq )
+{
+ OUStringBuffer buf(128);
+ int len = seq.getLength();
+ buf.append( "{" );
+ for( int i = 0 ; i < len ; i ++ )
+ {
+ OUString element;
+ seq[i] >>= element;
+
+ if( i > 0 )
+ buf.append( "," );
+ int strLength = element.getLength();
+ buf.append( "\"" );
+ for( int j = 0 ; j < strLength ; j ++ )
+ {
+ sal_Unicode c = element[j];
+ if( c == '\\' || c == '"' || c == '{' || c == '}' )
+ {
+ buf.append( "\\" );
+ }
+ buf.append( c );
+ }
+ buf.append( "\"" );
+ }
+ buf.append( "}" );
+ return buf.makeStringAndClear();
+}
+
+
+std::vector< Any > parseArray( const OUString & str )
+{
+ int len = str.getLength();
+ bool doubleQuote = false;
+ int brackets = 0;
+ int i = 0;
+
+ OUStringBuffer current;
+ std::vector<Any> elements;
+ bool doubleQuotedValue = false;
+ while( i < len )
+ {
+ sal_Unicode c = str[i];
+ sal_Unicode cnext = str[i+1];
+ if( doubleQuote )
+ {
+ if( '\\' == c )
+ {
+ i ++;
+ current.append( cnext );
+ }
+ else if( '"' == c )
+ {
+ doubleQuote = false;
+ doubleQuotedValue = true; // signal, that there was an empty element
+ }
+ else
+ {
+ current.append( c );
+ }
+ }
+ else if ( '{' == c )
+ {
+ brackets ++;
+ }
+ else if( '}' == c )
+ {
+ brackets --;
+ if( brackets < 0 )
+ {
+ throw SQLException(
+ "error during array parsing, didn't expect a } at position "
+ + OUString::number(i) + " ('" + str + "')",
+ Reference< XInterface > (), OUString(), 1, Any() );
+ }
+ if( brackets == 0 )
+ {
+ if( !current.isEmpty() || doubleQuotedValue )
+ elements.push_back( Any( current.makeStringAndClear() ) );
+ }
+ else
+ {
+ current.append( c );
+ }
+ }
+ else if( '"' == c )
+ {
+// if( current.getLength() != 0 )
+// {
+// OUStringBuffer buf;
+// buf.appendAscii( "error during array parsing, didn't expect a \" at position " );
+// buf.append( i );
+// buf.append( " ('" );
+// buf.append( str );
+// buf.append( "')" );
+// throw SDBCException(
+// buf.makeStringAndClear(),
+// Reference< XInterface > (), 1, Any() );
+// }
+// else
+// {
+ doubleQuote = true;
+// }
+ }
+ else if( ',' == c && brackets == 1)
+ {
+ doubleQuotedValue = false;
+ elements.push_back( Any( current.makeStringAndClear() ) );
+ }
+ else if( isWhitespace( c ) )
+ {
+ // ignore whitespace without quotes
+ }
+ else
+ {
+ current.append( c );
+ }
+ i++;
+ }
+ return elements;
+}
+
+std::vector< sal_Int32 > parseIntArray( const OUString & str )
+{
+ sal_Int32 start = 0;
+ std::vector<sal_Int32> vec;
+// printf( ">%s<\n" , OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
+ for( sal_Int32 i = str.indexOf( ' ' ) ; i != -1 ; i = str.indexOf( ' ', start) )
+ {
+ vec.push_back( rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
+// printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
+ start = i + 1;
+ }
+ vec.push_back( rtl_ustr_toInt32( &str.pData->buffer[start], 10 ) );
+// printf( "found %d\n" , rtl_ustr_toInt32( &str.pData->buffer[start], 10 ));
+ return vec;
+}
+
+void fillAttnum2attnameMap(
+ Int2StringMap &map,
+ const Reference< css::sdbc::XConnection > &conn,
+ const OUString &schema,
+ const OUString &table )
+{
+ Reference< XPreparedStatement > prep = conn->prepareStatement(
+ "SELECT attname,attnum "
+ "FROM pg_attribute "
+ "INNER JOIN pg_class ON attrelid = pg_class.oid "
+ "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
+ "WHERE relname=? AND nspname=?" );
+
+ Reference< XParameters > paras( prep, UNO_QUERY_THROW );
+ paras->setString( 1 , table );
+ paras->setString( 2 , schema );
+ Reference< XResultSet > rs = prep->executeQuery();
+
+ Reference< XRow > xRow( rs , UNO_QUERY_THROW );
+ while( rs->next() )
+ {
+ map[ xRow->getInt(2) ] = xRow->getString(1);
+ }
+}
+
+OString extractSingleTableFromSelect( const std::vector< OString > &vec )
+{
+ OString ret;
+
+ if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ vec[0].pData->buffer, vec[0].pData->length, "select" , 6 , 6 ) )
+ {
+ size_t token = 0;
+
+ for( token = 1; token < vec.size() ; token ++ )
+ {
+ if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ vec[token].getStr(), vec[token].getLength(), "from" , 4 , 4 ) )
+ {
+ // found from
+ break;
+ }
+ }
+ token ++;
+
+ if( token < vec.size() && 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ vec[token].pData->buffer, vec[token].pData->length, "only " , 4 , 4 ) )
+ {
+ token ++;
+ }
+
+ if( token < vec.size() && vec[token] != "(" )
+ {
+ // it is a table or a function name
+ OStringBuffer buf(128);
+ if( '"' == vec[token][0] )
+ buf.append( &(vec[token].getStr()[1]) , vec[token].getLength() -2 );
+ else
+ buf.append( vec[token] );
+ token ++;
+
+ if( token < vec.size() )
+ {
+ if( vec[token] == "." )
+ {
+ buf.append( vec[token] );
+ token ++;
+ if( token < vec.size() )
+ {
+ if( '"' == vec[token][0] )
+ buf.append( &(vec[token].getStr()[1]) , vec[token].getLength() -2 );
+ else
+ buf.append( vec[token] );
+ token ++;
+ }
+ }
+ }
+
+ ret = buf.makeStringAndClear();
+ // now got my table candidate
+
+ if( token < vec.size() && vec[token] == "(" )
+ {
+ // whoops, it is a function
+ ret.clear();
+ }
+ else
+ {
+ if( token < vec.size() )
+ {
+ if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ vec[token].pData->buffer, vec[token].pData->length, "as" , 2, 2 ) )
+ {
+ token += 2; // skip alias
+ }
+ }
+
+ if( token < vec.size() )
+ {
+ if( vec[token] == "," )
+ {
+ // whoops, multiple tables are used
+ ret.clear();
+ }
+ else
+ {
+ static const char * forbiddenKeywords[] =
+ { "join", "natural", "outer", "inner", "left", "right", "full" , nullptr };
+ for( int i = 0 ; forbiddenKeywords[i] ; i ++ )
+ {
+ size_t nKeywordLen = strlen(forbiddenKeywords[i]);
+ if( 0 == rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ vec[token].pData->buffer, vec[token].pData->length,
+ forbiddenKeywords[i], nKeywordLen,
+ nKeywordLen ) )
+ {
+ // whoops, it is a join
+ ret.clear();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return ret;
+
+}
+
+OUString getColExprForDefaultSettingVal(ConnectionSettings const *settings)
+{
+ return (PQserverVersion( settings->pConnection ) < 80000)?
+ OUString("pg_attrdef.adsrc"):
+ OUString("pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid, true)");
+}
+
+css::uno::Sequence< sal_Int32 > string2intarray( const OUString & str )
+{
+ css::uno::Sequence< sal_Int32 > ret;
+ const sal_Int32 strlen = str.getLength();
+ if( str.getLength() > 1 )
+ {
+ sal_Int32 start = 0;
+ sal_uInt32 c;
+ for (;;)
+ {
+ c = str.iterateCodePoints(&start);
+ if (!iswspace(c))
+ break;
+ if ( start == strlen)
+ return ret;
+ }
+ if ( c != L'{' )
+ return ret;
+ for (;;)
+ {
+ c = str.iterateCodePoints(&start);
+ if ( !iswspace(c) )
+ break;
+ if ( start == strlen)
+ return ret;
+ }
+ if ( c == L'}' )
+ return ret;
+
+ std::vector< sal_Int32 > vec;
+ do
+ {
+ OUStringBuffer digits;
+ do
+ {
+ if(!iswspace(c))
+ break;
+ if ( start == strlen)
+ return ret;
+ c=str.iterateCodePoints(&start);
+ } while ( c );
+ do
+ {
+ if (!iswdigit(c))
+ break;
+ if ( start == strlen)
+ return ret;
+ digits.append(OUString(&c, 1));
+ c = str.iterateCodePoints(&start);
+ } while ( c );
+ vec.push_back( digits.makeStringAndClear().toInt32() );
+ do
+ {
+ if(!iswspace(c))
+ break;
+ if ( start == strlen)
+ return ret;
+ c = str.iterateCodePoints(&start);
+ } while ( c );
+ if ( c == L'}' )
+ break;
+ if ( str.iterateCodePoints(&start) != L',' )
+ return ret;
+ if ( start == strlen)
+ return ret;
+ } while( true );
+ // vec is guaranteed non-empty
+ assert(vec.size() > 0);
+ ret = css::uno::Sequence< sal_Int32 > ( vec.data() , vec.size() );
+ }
+ return ret;
+}
+
+
+Sequence< OUString > convertMappedIntArray2StringArray(
+ const Int2StringMap &map, const Sequence< sal_Int32 > &intArray )
+{
+ Sequence< OUString > ret( intArray.getLength() );
+ auto retRange = asNonConstRange(ret);
+ for( int i = 0; i < intArray.getLength() ; i ++ )
+ {
+ Int2StringMap::const_iterator ii = map.find( intArray[i] );
+ if( ii != map.end() )
+ retRange[i] = ii->second;
+ }
+ return ret;
+}
+
+
+OUString sqltype2string( const Reference< XPropertySet > & desc )
+{
+ OUStringBuffer typeName;
+ typeName.append( extractStringProperty( desc, getStatics().TYPE_NAME ) );
+ sal_Int32 precision = extractIntProperty( desc, getStatics().PRECISION );
+
+ if( precision )
+ {
+ switch( extractIntProperty( desc, getStatics().TYPE ) )
+ {
+ case css::sdbc::DataType::VARBINARY:
+ case css::sdbc::DataType::VARCHAR:
+ case css::sdbc::DataType::CHAR:
+ {
+ typeName.append( "(" );
+ typeName.append( precision );
+ typeName.append( ")" );
+ break;
+ }
+ case css::sdbc::DataType::DECIMAL:
+ case css::sdbc::DataType::NUMERIC:
+ {
+ typeName.append( "(" );
+ typeName.append( precision );
+ typeName.append( "," );
+ typeName.append( extractIntProperty( desc, getStatics().SCALE ) );
+ typeName.append( ")" );
+ break;
+ }
+ default:
+ ((void)0);
+ }
+ }
+ return typeName.makeStringAndClear();
+}
+
+
+static void keyType2String( OUStringBuffer & buf, sal_Int32 keyType )
+{
+ if( css::sdbc::KeyRule::CASCADE == keyType )
+ {
+ buf.append( "CASCADE " );
+ }
+ else if( css::sdbc::KeyRule::RESTRICT == keyType )
+ {
+ buf.append( "RESTRICT " );
+ }
+ else if( css::sdbc::KeyRule::SET_DEFAULT == keyType )
+ {
+ buf.append( "SET DEFAULT " );
+ }
+ else if( css::sdbc::KeyRule::SET_NULL == keyType )
+ {
+ buf.append( "SET NULL " );
+ }
+ else //if( css::sdbc::KeyRule::NO_ACTION == keyType )
+ {
+ buf.append( "NO ACTION " );
+ }
+}
+
+void bufferKey2TableConstraint(
+ OUStringBuffer &buf, const Reference< XPropertySet > &key, ConnectionSettings *settings )
+{
+ Statics &st = getStatics();
+ sal_Int32 type = extractIntProperty( key, st.TYPE );
+ OUString referencedTable = extractStringProperty( key, st.REFERENCED_TABLE );
+ sal_Int32 updateRule = extractIntProperty( key, st.UPDATE_RULE );
+ sal_Int32 deleteRule = extractIntProperty( key, st.DELETE_RULE );
+ bool foreign = false;
+ if( type == css::sdbcx::KeyType::UNIQUE )
+ {
+ buf.append( "UNIQUE( " );
+ }
+ else if( type == css::sdbcx::KeyType::PRIMARY )
+ {
+ buf.append( "PRIMARY KEY( " );
+ }
+ else if( type == css::sdbcx::KeyType::FOREIGN )
+ {
+ foreign = true;
+ buf.append( "FOREIGN KEY( " );
+ }
+
+ Reference< XColumnsSupplier > columns( key, UNO_QUERY );
+ if( columns.is() )
+ {
+ Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY );
+ if( colEnumAccess.is() )
+ {
+ Reference< XEnumeration > colEnum = colEnumAccess->createEnumeration();
+ bool first = true;
+ while(colEnum.is() && colEnum->hasMoreElements() )
+ {
+ if( first )
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append( ", " );
+ }
+ Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY_THROW );
+ bufferQuoteIdentifier(buf, extractStringProperty( keyColumn, st.NAME ), settings );
+ }
+ }
+ }
+ buf.append( ") " );
+
+ if( !foreign )
+ return;
+
+ buf.append( "REFERENCES " );
+ OUString schema;
+ OUString tableName;
+ splitConcatenatedIdentifier( referencedTable, &schema, &tableName );
+ bufferQuoteQualifiedIdentifier(buf , schema, tableName, settings );
+ if(columns.is() )
+ {
+ Reference< XEnumerationAccess > colEnumAccess( columns->getColumns(), UNO_QUERY);
+ if( colEnumAccess.is() )
+ {
+ buf.append( " (" );
+ Reference< XEnumeration > colEnum(colEnumAccess->createEnumeration());
+ bool first = true;
+ while(colEnum.is() && colEnum->hasMoreElements() )
+ {
+ if( first )
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append( ", " );
+ }
+ Reference< XPropertySet > keyColumn( colEnum->nextElement(), UNO_QUERY_THROW );
+ bufferQuoteIdentifier(
+ buf, extractStringProperty( keyColumn, st.RELATED_COLUMN ), settings );
+ }
+ buf.append( ") " );
+ }
+ }
+
+ buf.append( "ON DELETE " );
+ keyType2String( buf, deleteRule );
+ buf.append( " ON UPDATE " );
+ keyType2String( buf, updateRule );
+
+}
+
+void extractNameValuePairsFromInsert( String2StringMap & map, const OString & lastQuery )
+{
+ std::vector< OString > vec;
+ tokenizeSQL( lastQuery, vec );
+
+ int nSize = vec.size();
+// printf( "1 %d\n", nSize );
+ if( !(nSize > 6 &&
+ vec[0].equalsIgnoreAsciiCase( "insert" ) &&
+ vec[1].equalsIgnoreAsciiCase( "into" )) )
+ return;
+
+ int n = 2;
+
+// printf( "1a\n" );
+ // skip table name
+ if( vec[n+1].equalsIgnoreAsciiCase( "." ) )
+ {
+ n +=2;
+ }
+
+ n ++;
+ if( !vec[n].equalsIgnoreAsciiCase( "(" ) )
+ return;
+
+ std::vector< OString> names;
+// printf( "2\n" );
+ // extract names
+ n++;
+ while( nSize > n && ! vec[n].equalsIgnoreAsciiCase( ")" ) )
+ {
+ names.push_back( vec[n] );
+ if( nSize > n+1 && vec[n+1].equalsIgnoreAsciiCase( "," ) )
+ {
+ n ++;
+ }
+ n++;
+ }
+ n++;
+
+ // now read the values
+ if( !(nSize > n +1 && vec[n].equalsIgnoreAsciiCase("VALUES") &&
+ vec[n+1].equalsIgnoreAsciiCase( "(" )) )
+ return;
+
+ n +=2;
+// printf( "3\n" );
+ for (auto& name : names)
+ {
+ if (n >= nSize)
+ break;
+
+ map[name] = vec[n];
+ if( nSize > n+1 && vec[n+1].equalsIgnoreAsciiCase(",") )
+ {
+ n ++;
+ }
+ n++;
+ }
+}
+
+OUString querySingleValue(
+ const css::uno::Reference< css::sdbc::XConnection > &connection,
+ const OUString &query )
+{
+ OUString ret;
+ Reference< XStatement > stmt = connection->createStatement();
+ DisposeGuard guard( stmt );
+ Reference< XResultSet > rs = stmt->executeQuery( query );
+ Reference< XRow > xRow( rs, UNO_QUERY );
+ if( rs->next() )
+ ret = xRow->getString( 1 );
+ return ret;
+}
+
+
+// copied from connectivity/source/dbtools, can't use the function directly
+bool implSetObject( const Reference< XParameters >& _rxParameters,
+ const sal_Int32 _nColumnIndex, const Any& _rValue)
+{
+ bool bSuccessfullyReRouted = true;
+ switch (_rValue.getValueTypeClass())
+ {
+ case css::uno::TypeClass_HYPER:
+ {
+ _rxParameters->setLong( _nColumnIndex, sal_Int64(0) );
+ }
+ break;
+
+ case css::uno::TypeClass_VOID:
+ _rxParameters->setNull(_nColumnIndex,css::sdbc::DataType::VARCHAR);
+ break;
+
+ case css::uno::TypeClass_STRING:
+ _rxParameters->setString(_nColumnIndex, *o3tl::forceAccess<OUString>(_rValue));
+ break;
+
+ case css::uno::TypeClass_BOOLEAN:
+ _rxParameters->setBoolean(_nColumnIndex, *o3tl::forceAccess<bool>(_rValue));
+ break;
+
+ case css::uno::TypeClass_BYTE:
+ _rxParameters->setByte(_nColumnIndex, *o3tl::forceAccess<sal_Int8>(_rValue));
+ break;
+
+ case css::uno::TypeClass_UNSIGNED_SHORT:
+ case css::uno::TypeClass_SHORT:
+ _rxParameters->setShort(_nColumnIndex, *o3tl::forceAccess<sal_Int16>(_rValue));
+ break;
+
+ case css::uno::TypeClass_CHAR:
+ _rxParameters->setString(_nColumnIndex, OUString(*o3tl::forceAccess<sal_Unicode>(_rValue)));
+ break;
+
+ case css::uno::TypeClass_UNSIGNED_LONG:
+ case css::uno::TypeClass_LONG:
+ _rxParameters->setInt(_nColumnIndex, *o3tl::forceAccess<sal_Int32>(_rValue));
+ break;
+
+ case css::uno::TypeClass_FLOAT:
+ _rxParameters->setFloat(_nColumnIndex, *o3tl::forceAccess<float>(_rValue));
+ break;
+
+ case css::uno::TypeClass_DOUBLE:
+ _rxParameters->setDouble(_nColumnIndex, *o3tl::forceAccess<double>(_rValue));
+ break;
+
+ case css::uno::TypeClass_SEQUENCE:
+ if (auto s = o3tl::tryAccess<Sequence< sal_Int8 >>(_rValue))
+ {
+ _rxParameters->setBytes(_nColumnIndex, *s);
+ }
+ else
+ bSuccessfullyReRouted = false;
+ break;
+ case css::uno::TypeClass_STRUCT:
+ if (auto s1 = o3tl::tryAccess<css::util::DateTime>(_rValue))
+ _rxParameters->setTimestamp(_nColumnIndex, *s1);
+ else if (auto s2 = o3tl::tryAccess<css::util::Date>(_rValue))
+ _rxParameters->setDate(_nColumnIndex, *s2);
+ else if (auto s3 = o3tl::tryAccess<css::util::Time>(_rValue))
+ _rxParameters->setTime(_nColumnIndex, *s3);
+ else
+ bSuccessfullyReRouted = false;
+ break;
+
+ case css::uno::TypeClass_INTERFACE:
+ {
+ Reference< css::io::XInputStream > xStream;
+ if (_rValue >>= xStream)
+ {
+ _rValue >>= xStream;
+ _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available());
+ break;
+ }
+ [[fallthrough]];
+ }
+ default:
+ bSuccessfullyReRouted = false;
+
+ }
+
+ return bSuccessfullyReRouted;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_tools.hxx b/connectivity/source/drivers/postgresql/pq_tools.hxx
new file mode 100644
index 000000000..1f9356ed4
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_tools.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <rtl/string.hxx>
+
+#include "pq_connection.hxx"
+
+#include <string_view>
+#include <vector>
+
+namespace
+{
+// helper to create one-time deleters
+template <auto fn>
+using deleter_from_fn = std::integral_constant<decltype(fn), fn>;
+
+}
+
+namespace pq_sdbc_driver
+{
+bool isWhitespace( sal_Unicode c );
+
+OUString concatQualified( std::u16string_view a, std::u16string_view b);
+
+OString OUStringToOString( std::u16string_view str, ConnectionSettings const *settings);
+
+void bufferQuoteConstant( OUStringBuffer & buf, std::u16string_view str, ConnectionSettings *settings );
+void bufferQuoteAnyConstant( OUStringBuffer & buf, const css::uno::Any &val, ConnectionSettings *settings );
+
+void bufferEscapeConstant( OUStringBuffer & buf, std::u16string_view str, ConnectionSettings *settings );
+
+OUString sqltype2string(
+ const css::uno::Reference< css::beans::XPropertySet > & column );
+
+
+void bufferQuoteQualifiedIdentifier(
+ OUStringBuffer & buf, std::u16string_view schema, std::u16string_view name, ConnectionSettings *settings );
+
+void bufferQuoteQualifiedIdentifier(
+ OUStringBuffer & buf,
+ std::u16string_view schema,
+ std::u16string_view name,
+ std::u16string_view col,
+ ConnectionSettings *settings );
+
+void bufferQuoteIdentifier( OUStringBuffer & buf, std::u16string_view toQuote, ConnectionSettings *settings );
+void bufferKey2TableConstraint(
+ OUStringBuffer &buf,
+ const css::uno::Reference< css::beans::XPropertySet > &key,
+ ConnectionSettings *settings );
+
+OUString extractStringProperty(
+ const css::uno::Reference< css::beans::XPropertySet > & descriptor,
+ const OUString &name );
+
+sal_Int32 extractIntProperty(
+ const css::uno::Reference< css::beans::XPropertySet > & descriptor,
+ const OUString &name );
+
+bool extractBoolProperty(
+ const css::uno::Reference< css::beans::XPropertySet > & descriptor,
+ const OUString &name );
+
+void disposeNoThrow( const css::uno::Reference< css::uno::XInterface > & r );
+void disposeObject( const css::uno::Reference< css::uno::XInterface > & r );
+
+OUString extractTableFromInsert( const OUString & sql );
+OString extractSingleTableFromSelect( const std::vector< OString > &vec );
+
+OUString getColExprForDefaultSettingVal(ConnectionSettings const *settings);
+
+void tokenizeSQL( const OString & sql, std::vector< OString > &vec );
+void splitSQL( const OString & sql, std::vector< OString > &vec );
+std::vector< sal_Int32 > parseIntArray( const OUString & str );
+/// @throws css::sdbc::SQLException
+std::vector< css::uno::Any > parseArray( const OUString & str );
+
+OUString array2String( const css::uno::Sequence< css::uno::Any > &seq );
+
+css::uno::Reference< css::sdbc::XConnection > extractConnectionFromStatement(
+ const css::uno::Reference< css::uno::XInterface > & stmt );
+
+void splitConcatenatedIdentifier( std::u16string_view source, OUString *first, OUString *second);
+
+
+void fillAttnum2attnameMap(
+ Int2StringMap &map,
+ const css::uno::Reference< css::sdbc::XConnection > &conn,
+ const OUString &schema,
+ const OUString &table );
+
+css::uno::Sequence< sal_Int32 > string2intarray( const OUString & str );
+
+css::uno::Sequence< OUString > convertMappedIntArray2StringArray(
+ const Int2StringMap &map, const css::uno::Sequence< sal_Int32> &source );
+
+typedef std::unordered_map< OString, OString > String2StringMap;
+
+OUString querySingleValue(
+ const css::uno::Reference< css::sdbc::XConnection > &connection,
+ const OUString &query );
+
+void extractNameValuePairsFromInsert( String2StringMap & map, const OString & lastQuery );
+sal_Int32 typeNameToDataType( const OUString &typeName, std::u16string_view typtype );
+
+// copied from connectivity/source/dbtools, can't use the function directly
+bool implSetObject( const css::uno::Reference< css::sdbc::XParameters >& _rxParameters,
+ const sal_Int32 _nColumnIndex, const css::uno::Any& _rValue);
+
+class DisposeGuard
+{
+ css::uno::Reference< css::uno::XInterface > d;
+public:
+ explicit DisposeGuard(const css::uno::Reference< css::uno::XInterface > & r );
+ ~DisposeGuard();
+
+};
+
+class TransactionGuard
+{
+ css::uno::Reference< css::sdbc::XStatement > m_stmt;
+ bool m_commited;
+public:
+ /// takes over ownership of given statement
+ explicit TransactionGuard( const css::uno::Reference< css::sdbc::XStatement > &stmt );
+ ~TransactionGuard( );
+
+ void commit();
+ void executeUpdate( const OUString & sql );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_updateableresultset.cxx b/connectivity/source/drivers/postgresql/pq_updateableresultset.cxx
new file mode 100644
index 000000000..5c1b23e82
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_updateableresultset.cxx
@@ -0,0 +1,550 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 200? by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
+
+#include "pq_updateableresultset.hxx"
+#include "pq_resultsetmetadata.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+#include <string.h>
+
+#include <connectivity/dbconversion.hxx>
+
+using osl::MutexGuard;
+
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::sdbc::XGeneratedResultSet;
+using com::sun::star::sdbc::XResultSetMetaDataSupplier;
+using com::sun::star::sdbc::SQLException;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XCloseable;
+using com::sun::star::sdbc::XColumnLocate;
+using com::sun::star::sdbc::XResultSetUpdate;
+using com::sun::star::sdbc::XRowUpdate;
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+
+using com::sun::star::beans::XFastPropertySet;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::beans::XMultiPropertySet;
+
+using namespace dbtools;
+
+namespace pq_sdbc_driver
+{
+
+
+css::uno::Reference< css::sdbc::XCloseable > UpdateableResultSet::createFromPGResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ ConnectionSettings **ppSettings,
+ PGresult *result,
+ const OUString &schema,
+ const OUString &table,
+ std::vector< OUString > && primaryKey )
+{
+ sal_Int32 columnCount = PQnfields( result );
+ sal_Int32 rowCount = PQntuples( result );
+ std::vector< OUString > columnNames( columnCount );
+ for( int i = 0 ; i < columnCount ; i ++ )
+ {
+ char * name = PQfname( result, i );
+ columnNames[i] = OUString( name, strlen(name), ConnectionSettings::encoding );
+ }
+ std::vector< std::vector< Any > > data( rowCount );
+
+ // copy all the data into unicode strings (also binaries, as we yet
+ // don't know, what a binary is and what not!)
+ for( int row = 0 ; row < rowCount ; row ++ )
+ {
+ std::vector< Any > aRow( columnCount );
+ for( int col = 0 ; col < columnCount ; col ++ )
+ {
+ if( ! PQgetisnull( result, row, col ) )
+ {
+ char * val = PQgetvalue( result, row, col );
+
+ aRow[col] <<=
+ OUString( val, strlen( val ), ConnectionSettings::encoding );
+ }
+ }
+ data[row] = aRow;
+ }
+
+ rtl::Reference<UpdateableResultSet> pRS = new UpdateableResultSet(
+ mutex, owner, std::move(columnNames), std::move(data), ppSettings, schema, table, std::move(primaryKey) );
+
+ pRS->m_meta = new ResultSetMetaData( mutex, pRS,nullptr, ppSettings, result, schema, table );
+
+ PQclear( result ); // we don't need it anymore
+
+ return pRS;
+}
+
+css::uno::Any UpdateableResultSet::queryInterface(
+ const css::uno::Type & reqType )
+{
+ Any ret = SequenceResultSet::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< XResultSetUpdate * > ( this ),
+ static_cast< XRowUpdate * > ( this ) );
+ return ret;
+}
+
+
+css::uno::Sequence< css::uno::Type > UpdateableResultSet::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<XResultSetUpdate>::get(),
+ cppu::UnoType<XRowUpdate>::get(),
+ SequenceResultSet::getTypes());
+
+ return collection.getTypes();
+
+}
+
+css::uno::Sequence< sal_Int8> UpdateableResultSet::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+OUString UpdateableResultSet::buildWhereClause()
+{
+ OUString ret;
+ if( !m_primaryKey.empty() )
+ {
+ OUStringBuffer buf( 128 );
+ buf.append( " WHERE " );
+ for( size_t i = 0 ; i < m_primaryKey.size() ; i ++ )
+ {
+ if( i > 0 )
+ buf.append( " AND " );
+ sal_Int32 index = findColumn( m_primaryKey[i] );
+ bufferQuoteIdentifier( buf, m_primaryKey[i], *m_ppSettings );
+ buf.append( " = " );
+ bufferQuoteConstant( buf, getString( index ), *m_ppSettings );
+ }
+ ret = buf.makeStringAndClear();
+ }
+ return ret;
+}
+
+
+void UpdateableResultSet::insertRow( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ SAL_INFO("connectivity.postgresql", "UpdateableResultSet::insertRow() got called");
+
+ if( ! m_insertRow )
+ throw SQLException(
+ "pq_resultset.insertRow: moveToInsertRow has not been called !",
+ *this, OUString(), 1, Any() );
+
+ OUStringBuffer buf( 128 );
+ buf.append( "INSERT INTO " );
+ bufferQuoteQualifiedIdentifier( buf, m_schema, m_table, *m_ppSettings );
+ buf.append( " ( " );
+
+ int columns = 0;
+ for( UpdateableFieldVector::size_type i = 0 ; i < m_updateableField.size() ; i++ )
+ {
+ if( m_updateableField[i].isTouched )
+ {
+ if( columns > 0 )
+ buf.append( ", " );
+ columns ++;
+ bufferQuoteIdentifier( buf, m_columnNames[i], *m_ppSettings);
+ }
+ }
+ buf.append( " ) VALUES ( " );
+
+ columns = 0;
+ for(const UpdateableField & i : m_updateableField)
+ {
+ if( i.isTouched )
+ {
+ if( columns > 0 )
+ buf.append( " , " );
+ columns ++;
+ bufferQuoteAnyConstant( buf, i.value, *m_ppSettings );
+
+// OUString val;
+// m_updateableField[i].value >>= val;
+// buf.append( val );
+// OStringToOUString(val, (*m_ppSettings)->encoding ) );
+ }
+ }
+
+ buf.append( " )" );
+
+ Reference< XStatement > stmt =
+ extractConnectionFromStatement(m_owner)->createStatement();
+ DisposeGuard dispGuard( stmt );
+ stmt->executeUpdate( buf.makeStringAndClear() );
+
+ // reflect the changes !
+ m_rowCount ++;
+ m_data.resize( m_rowCount );
+ m_data[m_rowCount-1] = std::vector< Any > ( m_fieldCount );
+ Reference< XGeneratedResultSet > result( stmt, UNO_QUERY );
+ if( result.is() )
+ {
+ Reference< XResultSet > rs = result->getGeneratedValues();
+ if( rs.is() && rs->next() )
+ {
+ Reference< XColumnLocate > columnLocate( rs, UNO_QUERY );
+ Reference< XRow> xRow ( rs, UNO_QUERY );
+ for( int i = 0 ; i < m_fieldCount ; i++ )
+ {
+ int field = columnLocate->findColumn( m_columnNames[i] );
+ if( field >= 1 )
+ {
+ m_data[m_rowCount-1][i] <<= xRow->getString( field );
+// printf( "adding %s %s\n" ,
+// OUStringToOString( m_columnNames[i], RTL_TEXTENCODING_ASCII_US).getStr(),
+// OUStringToOString( xRow->getString( field ), RTL_TEXTENCODING_ASCII_US).getStr() );
+
+ }
+ }
+ }
+ else
+ {
+ // do the best we can ( DEFAULT and AUTO increment values fail ! )
+ for( int i = 0 ; i < m_fieldCount ; i ++ )
+ {
+ if( m_updateableField[i].isTouched )
+ m_data[m_rowCount-1][i] = m_updateableField[i].value;
+ }
+ }
+ }
+
+ // cleanup
+ m_updateableField = UpdateableFieldVector();
+}
+
+void UpdateableResultSet::updateRow( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ SAL_INFO("connectivity.postgresql", "UpdateableResultSet::updateRow() got called");
+
+ if( m_insertRow )
+ throw SQLException(
+ "pq_resultset.updateRow: moveToCurrentRow has not been called !",
+ *this, OUString(), 1, Any() );
+
+ OUStringBuffer buf( 128 );
+ buf.append( "UPDATE " );
+ bufferQuoteQualifiedIdentifier( buf, m_schema, m_table, *m_ppSettings );
+ buf.append( "SET " );
+
+ int columns = 0;
+ for( UpdateableFieldVector::size_type i = 0; i < m_updateableField.size() ; i ++ )
+ {
+ if( m_updateableField[i].isTouched )
+ {
+ if( columns > 0 )
+ buf.append( ", " );
+ columns ++;
+
+ buf.append( m_columnNames[i] );
+ buf.append( " = " );
+ bufferQuoteAnyConstant( buf, m_updateableField[i].value, *m_ppSettings );
+// OUString val;
+// m_updateableField[i].value >>= val;
+// bufferQuoteConstant( buf, val ):
+// buf.append( val );
+ }
+ }
+ buf.append( buildWhereClause() );
+
+ Reference< XStatement > stmt = extractConnectionFromStatement(m_owner)->createStatement();
+ DisposeGuard dispGuard( stmt );
+ stmt->executeUpdate( buf.makeStringAndClear() );
+
+ // reflect the changes !
+ for( int i = 0 ; i < m_fieldCount ; i ++ )
+ {
+ if( m_updateableField[i].isTouched )
+ m_data[m_row][i] = m_updateableField[i].value;
+ }
+ m_updateableField = UpdateableFieldVector();
+}
+
+void UpdateableResultSet::deleteRow( )
+{
+ SAL_INFO("connectivity.postgresql", "UpdateableResultSet::deleteRow() got called");
+
+ if( m_insertRow )
+ throw SQLException(
+ "pq_resultset.deleteRow: deleteRow cannot be called when on insert row !",
+ *this, OUString(), 1, Any() );
+
+ if( m_row < 0 || m_row >= m_rowCount )
+ {
+ throw SQLException(
+ "deleteRow cannot be called on invalid row ("
+ + OUString::number(m_row) + ")",
+ *this, OUString(), 0, Any() );
+ }
+
+ Reference< XStatement > stmt = extractConnectionFromStatement(m_owner)->createStatement();
+ DisposeGuard dispGuard( stmt );
+ OUStringBuffer buf( 128 );
+ buf.append( "DELETE FROM " );
+ bufferQuoteQualifiedIdentifier( buf, m_schema, m_table, *m_ppSettings );
+ buf.append( " " );
+ buf.append( buildWhereClause() );
+
+ stmt->executeUpdate( buf.makeStringAndClear() );
+
+ // reflect the changes !
+ for( int i = m_row + 1; i < m_row ; i ++ )
+ {
+ m_data[i-1] = m_data[i];
+ }
+ m_rowCount --;
+ m_data.resize( m_rowCount );
+ }
+
+void UpdateableResultSet::cancelRowUpdates( )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ m_updateableField = UpdateableFieldVector();
+}
+
+void UpdateableResultSet::moveToInsertRow( )
+{
+ m_insertRow = true;
+}
+
+void UpdateableResultSet::moveToCurrentRow( )
+{
+ m_insertRow = false;
+}
+
+void UpdateableResultSet::checkUpdate( sal_Int32 columnIndex)
+{
+ checkColumnIndex( columnIndex );
+ if( m_updateableField.empty() )
+ m_updateableField = UpdateableFieldVector( m_fieldCount );
+ m_updateableField[columnIndex-1].isTouched = true;
+}
+
+void UpdateableResultSet::updateNull( sal_Int32 columnIndex )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+ m_updateableField[columnIndex-1].value = Any();
+}
+
+void UpdateableResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+ Statics &st = getStatics();
+ m_updateableField[columnIndex-1].value <<= ( x ? st.TRUE : st.FALSE );
+
+}
+
+void UpdateableResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x )
+{
+ updateInt(columnIndex,x);
+}
+
+void UpdateableResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x )
+{
+ updateInt( columnIndex, x );
+}
+
+void UpdateableResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x )
+{
+ updateLong( columnIndex, x );
+// MutexGuard guard( m_xMutex->GetMutex() );
+// checkClosed();
+// checkUpdate( columnIndex );
+
+// m_updateableField[columnIndex-1].value <<= OUString::valueOf( x );
+
+}
+
+void UpdateableResultSet::updateLong( sal_Int32 columnIndex, sal_Int64 x )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+// OStringBuffer buf( 20 );
+// buf.append( "'" );
+// buf.append( (sal_Int64) x );
+// buf.append( "'" );
+ m_updateableField[columnIndex-1].value <<= OUString::number( x );
+}
+
+void UpdateableResultSet::updateFloat( sal_Int32 columnIndex, float x )
+{
+
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+ m_updateableField[columnIndex-1].value <<= OUString::number( x );
+}
+
+void UpdateableResultSet::updateDouble( sal_Int32 columnIndex, double x )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+ m_updateableField[columnIndex-1].value <<= OUString::number( x );
+}
+
+void UpdateableResultSet::updateString( sal_Int32 columnIndex, const OUString& x )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+ m_updateableField[columnIndex-1].value <<= x;
+}
+
+void UpdateableResultSet::updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ checkClosed();
+ checkUpdate( columnIndex );
+
+ size_t len;
+ unsigned char * escapedString =
+ PQescapeBytea( reinterpret_cast<unsigned char const *>(x.getConstArray()), x.getLength(), &len);
+ if( ! escapedString )
+ {
+ throw SQLException(
+ "pq_preparedstatement.setBytes: Error during converting bytesequence to an SQL conform string",
+ *this, OUString(), 1, Any() );
+ }
+// buf.append( (const char *)escapedString, len -1 );
+
+ m_updateableField[columnIndex-1].value <<=
+ OUString( reinterpret_cast<char*>(escapedString), len, RTL_TEXTENCODING_ASCII_US );
+ PQfreemem( escapedString );
+}
+
+void UpdateableResultSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x )
+{
+ updateString( columnIndex, DBTypeConversion::toDateString( x ) );
+}
+
+void UpdateableResultSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x )
+{
+ updateString( columnIndex, DBTypeConversion::toTimeString( x ) );
+}
+
+void UpdateableResultSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x )
+{
+ updateString( columnIndex, DBTypeConversion::toDateTimeString( x ) );
+}
+
+void UpdateableResultSet::updateBinaryStream( sal_Int32 /* columnIndex */, const css::uno::Reference< css::io::XInputStream >& /* x */, sal_Int32 /* length */ )
+{
+}
+
+void UpdateableResultSet::updateCharacterStream( sal_Int32 /* columnIndex */, const css::uno::Reference< css::io::XInputStream >& /* x */, sal_Int32 /* length */ )
+{
+}
+
+void UpdateableResultSet::updateObject( sal_Int32 /* columnIndex */, const css::uno::Any& /* x */ )
+{
+}
+
+void UpdateableResultSet::updateNumericObject( sal_Int32 /* columnIndex */, const css::uno::Any& /* x */, sal_Int32 /* scale */ )
+{
+}
+
+
+Sequence< Type > UpdateableResultSet::getStaticTypes( bool updateable )
+{
+ if( updateable )
+ {
+ cppu::OTypeCollection collection(
+ cppu::UnoType<XResultSetUpdate>::get(),
+ cppu::UnoType<XRowUpdate>::get(),
+// cppu::UnoType<css::sdbcx::XRowLocate>::get(),
+ getStaticTypes( false /* updateable */ ) );
+ return collection.getTypes();
+ }
+ else
+ {
+ cppu::OTypeCollection collection(
+ cppu::UnoType<XResultSet>::get(),
+ cppu::UnoType<XResultSetMetaDataSupplier>::get(),
+ cppu::UnoType<XRow>::get(),
+ cppu::UnoType<XColumnLocate>::get(),
+ cppu::UnoType<XCloseable>::get(),
+ cppu::UnoType<XPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<css::lang::XComponent>::get(), // OComponentHelper
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<css::uno::XAggregation>::get(),
+ cppu::UnoType<css::uno::XWeak>::get());
+ return collection.getTypes();
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_updateableresultset.hxx b/connectivity/source/drivers/postgresql/pq_updateableresultset.hxx
new file mode 100644
index 000000000..1beeadc31
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_updateableresultset.hxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 200? by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_sequenceresultset.hxx"
+#include "pq_resultsetmetadata.hxx"
+
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+
+namespace pq_sdbc_driver
+{
+
+struct UpdateableField
+{
+ UpdateableField( )
+ : isTouched(false)
+ {}
+ css::uno::Any value;
+ bool isTouched;
+};
+
+typedef std::vector< UpdateableField > UpdateableFieldVector;
+
+class UpdateableResultSet final :
+ public SequenceResultSet,
+ public css::sdbc::XResultSetUpdate,
+ public css::sdbc::XRowUpdate
+{
+ ConnectionSettings **m_ppSettings;
+ OUString m_schema;
+ OUString m_table;
+ std::vector< OUString > m_primaryKey;
+ UpdateableFieldVector m_updateableField;
+ bool m_insertRow;
+
+private:
+ UpdateableResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ std::vector< OUString >&& colNames,
+ std::vector< std::vector< css::uno::Any > >&& data,
+ ConnectionSettings **ppSettings,
+ const OUString &schema,
+ const OUString &table,
+ std::vector< OUString >&& primaryKey)
+ : SequenceResultSet( mutex, owner, std::move(colNames), std::move(data), (*ppSettings)->tc ),
+ m_ppSettings( ppSettings ),
+ m_schema( schema ),
+ m_table( table ),
+ m_primaryKey( std::move(primaryKey) ),
+ m_insertRow( false )
+ {
+ // LEM TODO: this duplicates code in pq_resultset.cxx, except for different value
+ // of ResultSetConcurrency. Baaad.
+ // Why is an updatable ResultSet a sequenceresultset in the first place?
+ // This seems to imply that the whole data is fetched once and kept in memory. BAAAAD.
+ // LEM TODO: shouldn't these things be inherited from the statement or something like that?
+ // Positioned update/delete not supported, so no cursor name
+ // Fetch direction and size are cursor-specific things, so not used now.
+ // Fetch size not set
+ m_props[ BASERESULTSET_FETCH_DIRECTION ] <<= css::sdbc::FetchDirection::UNKNOWN;
+ // No escape processing for now
+ m_props[ BASERESULTSET_ESCAPE_PROCESSING ] <<= false;
+ // Bookmarks not implemented for now
+ m_props[ BASERESULTSET_IS_BOOKMARKABLE ] <<= false;
+ m_props[ BASERESULTSET_RESULT_SET_CONCURRENCY ] <<=
+ css::sdbc::ResultSetConcurrency::UPDATABLE;
+ m_props[ BASERESULTSET_RESULT_SET_TYPE ] <<=
+ css::sdbc::ResultSetType::SCROLL_INSENSITIVE;
+ }
+
+ OUString buildWhereClause();
+ void checkUpdate( sal_Int32 column );
+
+public:
+ static css::uno::Reference< css::sdbc::XCloseable > createFromPGResultSet(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & mutex,
+ const css::uno::Reference< css::uno::XInterface > &owner,
+ ConnectionSettings **ppSettings,
+ PGresult *result,
+ const OUString &schema,
+ const OUString &table,
+ std::vector< OUString > && primaryKey );
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { SequenceResultSet::acquire(); }
+ virtual void SAL_CALL release() noexcept override { SequenceResultSet::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XResultSetUpdate
+ virtual void SAL_CALL insertRow( ) override;
+ virtual void SAL_CALL updateRow( ) override;
+ virtual void SAL_CALL deleteRow( ) override;
+ virtual void SAL_CALL cancelRowUpdates( ) override;
+ virtual void SAL_CALL moveToInsertRow( ) override;
+ virtual void SAL_CALL moveToCurrentRow( ) override;
+
+public: // XRowUpdate
+ virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) override;
+ virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) override;
+ virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) override;
+ virtual void SAL_CALL updateString( sal_Int32 columnIndex, const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) override;
+
+public:
+ /// @throws css::uno::RuntimeException
+ static css::uno::Sequence< css::uno::Type > getStaticTypes( bool updateable );
+
+};
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xbase.cxx b/connectivity/source/drivers/postgresql/pq_xbase.cxx
new file mode 100644
index 000000000..5dbe6e98b
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xbase.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/sequence.hxx>
+
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+#include "pq_xbase.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::RuntimeException;
+
+using com::sun::star::beans::Property;
+using com::sun::star::beans::XPropertySetInfo;
+using com::sun::star::beans::XPropertySet;
+
+namespace pq_sdbc_driver
+{
+
+ReflectionBase::ReflectionBase(
+ const OUString &implName,
+ const css::uno::Sequence< OUString > &supportedServices,
+ const ::rtl::Reference< comphelper::RefCountedMutex >& refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > &conn,
+ ConnectionSettings *pSettings,
+ cppu::IPropertyArrayHelper & props /* must survive this object !*/ )
+ : ReflectionBase_BASE( refMutex->GetMutex() ),
+ OPropertySetHelper( ReflectionBase_BASE::rBHelper ),
+ m_implName( implName ),
+ m_supportedServices( supportedServices ),
+ m_xMutex( refMutex ),
+ m_conn( conn ),
+ m_pSettings( pSettings ),
+ m_propsDesc( props ),
+ m_values( props.getProperties().getLength() )
+{}
+
+cppu::IPropertyArrayHelper & ReflectionBase::getInfoHelper()
+{
+ return m_propsDesc;
+}
+
+sal_Bool ReflectionBase::convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue )
+{
+
+ rOldValue = m_values[nHandle];
+ rConvertedValue = rValue; // TODO !!! implement correct conversion !
+ m_values[nHandle] = rValue;
+ return true;
+}
+
+void ReflectionBase::setPropertyValue_NoBroadcast_public(
+ const OUString & name, const css::uno::Any & value )
+{
+ sal_Int32 nHandle = m_propsDesc.getHandleByName( name );
+ if( -1 == nHandle )
+ {
+ throw css::uno::RuntimeException(
+ "Unknown property '" + name + "' in " + m_implName,
+ *this );
+ }
+ setFastPropertyValue_NoBroadcast( nHandle , value );
+}
+
+void ReflectionBase::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue )
+{
+// OUString s;
+// rValue >>= s;
+// printf( "setting value (handle %d):%s\n" ,
+// nHandle, OUStringToOString(s, RTL_TEXTENCODING_ASCII_US).getStr() );
+ m_values[nHandle] = rValue;
+}
+
+void ReflectionBase::getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle ) const
+{
+ rValue = m_values[nHandle];
+// OUString s;
+// rValue >>= s;
+// printf( "getting value (handle %d):%s\n" ,
+// nHandle, OUStringToOString(s, RTL_TEXTENCODING_ASCII_US).getStr() );
+
+}
+
+Reference < css::beans::XPropertySetInfo > ReflectionBase::getPropertySetInfo()
+{
+ return OPropertySetHelper::createPropertySetInfo( m_propsDesc );
+}
+
+OUString ReflectionBase::getImplementationName()
+{
+ return m_implName;
+}
+
+sal_Bool ReflectionBase::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > ReflectionBase::getSupportedServiceNames()
+{
+ return m_supportedServices;
+}
+
+
+Sequence< css::uno::Type > ReflectionBase::getTypes()
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ static Sequence< css::uno::Type > collection(
+ ::comphelper::concatSequences(
+ ::cppu::OPropertySetHelper::getTypes(),
+ ReflectionBase_BASE::getTypes() ) );
+ return collection;
+}
+
+
+css::uno::Any ReflectionBase::queryInterface(
+ const css::uno::Type & reqType )
+{
+ Any ret = ReflectionBase_BASE::queryInterface( reqType );
+ return ret.hasValue() ? ret : OPropertySetHelper::queryInterface( reqType );
+
+}
+
+Sequence< sal_Int8> ReflectionBase::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void ReflectionBase::copyValuesFrom( const Reference< XPropertySet > & set )
+{
+ Reference< XPropertySetInfo > info = set->getPropertySetInfo();
+ if( info.is () )
+ {
+ Reference< XPropertySetInfo > myPropInfo = getPropertySetInfo();
+
+ const Sequence< Property > props = info->getProperties();
+ for( Property const & prop : props )
+ {
+ if( myPropInfo->hasPropertyByName( prop.Name ) )
+ setPropertyValue_NoBroadcast_public(
+ prop.Name, set->getPropertyValue( prop.Name ) );
+ }
+ }
+}
+
+OUString ReflectionBase::getName( )
+{
+ Statics & st = getStatics();
+ if( getInfoHelper().hasPropertyByName( st.SCHEMA_NAME ) )
+ return concatQualified(
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ) );
+ else
+ return extractStringProperty( this, getStatics().NAME );
+}
+
+
+void ReflectionBase::setName( const OUString& /* aName */ )
+{
+ throw RuntimeException(
+ "pq_sdbc::ReflectionBase::setName not implemented",
+ *this );
+ //setPropertyValue( getStatics().NAME , makeAny( aName ) );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xbase.hxx b/connectivity/source/drivers/postgresql/pq_xbase.hxx
new file mode 100644
index 000000000..3cd16bc70
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xbase.hxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/compbase.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+typedef ::cppu::WeakComponentImplHelper< css::lang::XServiceInfo,
+ css::sdbcx::XDataDescriptorFactory,
+ css::container::XNamed
+ > ReflectionBase_BASE;
+
+class ReflectionBase :
+ public ReflectionBase_BASE,
+ public cppu::OPropertySetHelper
+{
+protected:
+ const OUString m_implName;
+ const css::uno::Sequence< OUString > m_supportedServices;
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ css::uno::Reference< css::sdbc::XConnection > m_conn;
+ ConnectionSettings *m_pSettings;
+ cppu::IPropertyArrayHelper & m_propsDesc;
+ std::vector< css::uno::Any > m_values;
+public:
+ ReflectionBase(
+ const OUString &implName,
+ const css::uno::Sequence< OUString > &supportedServices,
+ const ::rtl::Reference< comphelper::RefCountedMutex >& refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > &conn,
+ ConnectionSettings *pSettings,
+ cppu::IPropertyArrayHelper & props /* must survive this object !*/ );
+
+public:
+ void copyValuesFrom( const css::uno::Reference< css::beans::XPropertySet > &set );
+
+public: // for initialization purposes only, not exported via an interface !
+ void setPropertyValue_NoBroadcast_public(
+ const OUString & name, const css::uno::Any & value );
+
+public: //XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase_BASE::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase_BASE::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // OPropertySetHelper
+ virtual cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+
+ void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle ) const override;
+
+ // XPropertySet
+ css::uno::Reference < css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
+
+public: // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override = 0;
+
+public: // XNamed
+ virtual OUString SAL_CALL getName( ) override;
+ virtual void SAL_CALL setName( const OUString& aName ) override;
+
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcolumn.cxx b/connectivity/source/drivers/postgresql/pq_xcolumn.cxx
new file mode 100644
index 000000000..b19d95c3c
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcolumn.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+#include "pq_statics.hxx"
+#include "pq_xcolumn.hxx"
+
+using com::sun::star::uno::Reference;
+
+using com::sun::star::beans::XPropertySet;
+
+namespace pq_sdbc_driver
+{
+Column::Column( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.column.implName,
+ getStatics().refl.column.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.column.pProps )
+{}
+
+Reference< XPropertySet > Column::createDataDescriptor( )
+{
+ rtl::Reference<ColumnDescriptor> pColumn = new ColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pColumn->copyValuesFrom( this );
+ return Reference< XPropertySet > ( pColumn );
+}
+
+ColumnDescriptor::ColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.columnDescriptor.implName,
+ getStatics().refl.columnDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ *getStatics().refl.columnDescriptor.pProps )
+{}
+
+Reference< XPropertySet > ColumnDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<ColumnDescriptor> pColumn = new ColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pColumn->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pColumn );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcolumn.hxx b/connectivity/source/drivers/postgresql/pq_xcolumn.hxx
new file mode 100644
index 000000000..794b5851d
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcolumn.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class Column : public ReflectionBase
+{
+public:
+ Column( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+class ColumnDescriptor : public ReflectionBase
+{
+public:
+ ColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings );
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcolumns.cxx b/connectivity/source/drivers/postgresql/pq_xcolumns.cxx
new file mode 100644
index 000000000..f1d3c0a53
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcolumns.cxx
@@ -0,0 +1,560 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+
+#include <cppuhelper/exc_hlp.hxx>
+
+#include "pq_xcolumns.hxx"
+#include "pq_xcolumn.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::RuntimeException;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XDatabaseMetaData;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+static Any isCurrency( std::u16string_view typeName )
+{
+ return Any( o3tl::equalsIgnoreAsciiCase(typeName, u"money") );
+}
+
+// static sal_Bool isAutoIncrement8( const OUString & typeName )
+// {
+// return typeName.equalsIgnoreAsciiCase("serial8") ||
+// typeName.equalsIgnoreAsciiCase("bigserial");
+// }
+
+static Any isAutoIncrement( std::u16string_view defaultValue )
+{
+ bool ret = o3tl::starts_with( defaultValue, u"nextval(" );
+// printf( "%s %d\n",
+// OUStringToOString(defaultValue, RTL_TEXTENCODING_ASCII_US).getStr(),
+// ret );
+// {
+// static const char * const serials[] =
+// {
+// "serial", "serial4", "serial8", "bigserial", 0
+// };
+// s sal_Bool b = sal_False;
+// for( int i = 0; !b && serials[i] ; i ++ )
+// {
+// b = b || typeName.equalsIgnoreAsciiCaseAscii( serials[i] );
+// }
+ return Any ( ret );
+}
+
+Columns::Columns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName)
+ : Container( refMutex, origin, pSettings, "COLUMN" ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName )
+{}
+
+Columns::~Columns()
+{}
+
+OUString columnMetaData2SDBCX(
+ ReflectionBase *pBase, const css::uno::Reference< css::sdbc::XRow > &xRow )
+{
+ Statics & st = getStatics();
+
+ // 1. TABLE_CAT string => table catalog (may be NULL)
+ // => not supported
+ // 2. TABLE_SCHEM string => table schema (may be NULL)
+ // => pg_namespace.nspname
+ // 3. TABLE_NAME string => table name
+ // => pg_class.relname
+ // 4. COLUMN_NAME string => column name
+ // => pg_attribute.attname
+ // 5. DATA_TYPE short => SQL type from java.sql.Types
+ // => pg_type.typname => sdbc.DataType
+ // 6. TYPE_NAME string => Data source dependent type name, for a UDT the
+ // type name is fully qualified
+ // => pg_type.typname
+ // 7. COLUMN_SIZE long => column size. For char or date types this is
+ // the maximum number of characters, for numeric
+ // or decimal types this is precision.
+ // => pg_type.typlen ( TODO: What is about variable size ? )
+ // 8. BUFFER_LENGTH is not used.
+ // => not used
+ // 9. DECIMAL_DIGITS long => the number of fractional digits
+ // => don't know ! TODO !
+ // 10. NUM_PREC_RADIX long => Radix (typically either 10 or 2)
+ // => TODO ??
+ // 11. NULLABLE long => is NULL allowed?
+ // NO_NULLS - might not allow NULL values
+ // NULABLE - definitely allows NULL values
+ // NULLABLE_UNKNOWN - nullability unknown
+ // => pg_attribute.attnotnull
+ // 12. REMARKS string => comment describing column (may be NULL )
+ // => Don't know, there does not seem to exist something like
+ // that in postgres
+ // 13. COLUMN_DEF string => default value (may be NULL)
+ // => pg_type.typdefault
+ // 14. SQL_DATA_TYPE long => unused
+ // => empty
+ // 15. SQL_DATETIME_SUB long => unused
+ // => empty
+ // 16. CHAR_OCTET_LENGTH long => for char types the maximum number of
+ // bytes in the column
+ // => pg_type.typlen
+ // 17. ORDINAL_POSITION int => index of column in table (starting at 1)
+ // pg_attribute.attnum
+ // 18. IS_NULLABLE string => "NO" means column definitely does not allow
+ // NULL values; "YES" means the column might
+ // allow NULL values. An empty string means
+ // nobody knows.
+ // => pg_attribute.attnotnull
+
+ static const int COLUMN_NAME = 4;
+ static const int DATA_TYPE = 5;
+ static const int TYPE_NAME = 6;
+ static const int COLUMN_SIZE = 7;
+ static const int DECIMAL_DIGITS = 9;
+ static const int IS_NULLABLE = 11;
+ static const int DESCRIPTION = 12;
+ static const int DEFAULT_VALUE = 13;
+
+ OUString name = xRow->getString( COLUMN_NAME );
+ OUString typeName = xRow->getString( TYPE_NAME );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.NAME, Any( name ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.TYPE, Any( xRow->getInt( DATA_TYPE ) ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.TYPE_NAME, Any( typeName ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.PRECISION, Any( xRow->getInt( COLUMN_SIZE ) ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.SCALE, Any( xRow->getInt( DECIMAL_DIGITS ) ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.IS_NULLABLE, Any( xRow->getInt( IS_NULLABLE ) ) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.DEFAULT_VALUE, Any( xRow->getString( DEFAULT_VALUE ) ) );
+
+// pBase->setPropertyValue_NoBroadcast_public(
+// st.DESCRIPTION, makeAny( xRow->getString( DESCRIPTION ) ) );
+
+// if( pBase->getPropertySetInfo()->hasPropertyByName( st.HELP_TEXT ) )
+// pBase->setPropertyValue_NoBroadcast_public(
+// st.HELP_TEXT, makeAny( xRow->getString( DESCRIPTION ) ) );
+// else // for key columns, etc. ...
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.DESCRIPTION, Any( xRow->getString( DESCRIPTION ) ) );
+
+
+ // maybe a better criterion than the type name can be found in future
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.IS_AUTO_INCREMENT, isAutoIncrement(xRow->getString( DEFAULT_VALUE )) );
+
+ pBase->setPropertyValue_NoBroadcast_public(
+ st.IS_CURRENCY, isCurrency( typeName));
+ return name;
+}
+
+
+// class CommentChanger : public cppu::WeakImplHelper< XPropertyChangeListener >
+// {
+// ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+// css::uno::Reference< css::sdbc::XConnection > m_connection;
+// ConnectionSettings *m_pSettings;
+// OUString m_schema;
+// OUString m_table;
+// OUString m_column;
+
+// public:
+// CommentChanger(
+// const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+// const css::uno::Reference< css::sdbc::XConnection > & connection,
+// ConnectionSettings *pSettings,
+// const OUString & schema,
+// const OUString & table,
+// const OUString & column ) :
+// m_xMutex( refMutex ),
+// m_connection( connection ),
+// m_pSettings( pSettings ),
+// m_schema ( schema ),
+// m_table ( table ),
+// m_column ( column )
+// {}
+
+
+// // Methods
+// virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) throw (css::uno::RuntimeException)
+// {
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// m_connection.clear();
+// }
+// // Methods
+// virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) throw (css::uno::RuntimeException)
+// {
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// OUStringBuffer buf( 128 );
+// OUString comment;
+// evt.NewValue >>= comment;
+// buf.append( "COMMENT ON COLUMN" );
+// bufferQuoteQualifiedIdentifier( buf, m_schema, m_table , m_column );
+// buf.append( "IS " );
+// bufferQuoteConstant( buf, comment,m_pSettings->encoding);
+
+// printf( "changing comment of column %s to %s\n",
+// OUStringToOString( m_column, RTL_TEXTENCODING_ASCII_US ).getStr(),
+// OUStringToOString( comment, RTL_TEXTENCODING_ASCII_US ).getStr() );
+
+// m_connection->createStatement()->executeUpdate( buf.makeStringAndClear() );
+// }
+// };
+
+void Columns::refresh()
+{
+ try
+ {
+ SAL_INFO("connectivity.postgresql", "sdbcx.Columns get refreshed for table " << m_schemaName << "." << m_tableName);
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ Statics &st = getStatics();
+ Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
+
+ Reference< XResultSet > rs =
+ meta->getColumns( Any(), m_schemaName, m_tableName, st.cPERCENT );
+
+ DisposeGuard disposeIt( rs );
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ String2IntMap map;
+
+ m_values.clear();
+ int columnIndex = 0;
+ while( rs->next() )
+ {
+ rtl::Reference<Column> pColumn =
+ new Column( m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pColumn;
+
+ OUString name = columnMetaData2SDBCX( pColumn.get(), xRow );
+// pColumn->addPropertyChangeListener(
+// st.HELP_TEXT,
+// new CommentChanger(
+// m_xMutex,
+// m_origin,
+// m_pSettings,
+// m_schemaName,
+// m_tableName,
+// name ) );
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ name ] = columnIndex;
+ ++columnIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ nullptr, anyEx );
+ }
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void alterColumnByDescriptor(
+ std::u16string_view schemaName,
+ std::u16string_view tableName,
+ ConnectionSettings *settings,
+ const Reference< XStatement > &stmt,
+ const css::uno::Reference< css::beans::XPropertySet > & past,
+ const css::uno::Reference< css::beans::XPropertySet > & future)
+{
+ Statics & st = getStatics();
+
+// if( past->getPropertyValue( st.TABLE_NAME ) != future->getPropertyValue( st.TABLE_NAME ) ||
+// past->getPropertyValue( st.SCHEMA_NAME ) != future->getPropertyValue( st.SCHEMA_NAME ))
+// {
+// OUStringBuffer buf(128);
+// buf.append( "Can't move column " );
+// buf.append( extractStringProperty( past, st.COLUMN_NAME ) );
+// buf.append( " from table " );
+// buf.append( extractStringProperty( past, st.TABLE_NAME ) );
+// buf.append( " to table " );
+// buf.append( extractStringProperty( past, st.TABLE_NAME ) );
+// throw SQLException( buf.makeStringAndClear() );
+// }
+
+// OUString tableName = extractStringProperty( past, st.TABLE_NAME );
+// OUString schemaName = extractStringProperty( past, st.SCHEMA_NAME );
+ OUString pastColumnName = extractStringProperty( past, st.NAME );
+ OUString futureColumnName = extractStringProperty( future, st.NAME );
+ OUString pastTypeName = sqltype2string( past );
+ OUString futureTypeName = sqltype2string( future );
+
+ TransactionGuard transaction( stmt );
+
+ OUStringBuffer buf( 128 );
+ if( ! pastColumnName.getLength())
+ {
+ // create a new column
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schemaName, tableName, settings );
+ buf.append( "ADD COLUMN" );
+ bufferQuoteIdentifier( buf, futureColumnName, settings );
+ buf.append( futureTypeName );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+ else
+ {
+ if( pastTypeName != futureTypeName )
+ {
+ throw RuntimeException(
+ "Can't modify column types, drop the column and create a new one" );
+ }
+
+ if( pastColumnName != futureColumnName )
+ {
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schemaName, tableName, settings );
+ buf.append( "RENAME COLUMN" );
+ bufferQuoteIdentifier( buf, pastColumnName, settings );
+ buf.append( "TO" );
+ bufferQuoteIdentifier( buf, futureColumnName, settings );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+ }
+
+ OUString futureDefaultValue = extractStringProperty( future, st.DEFAULT_VALUE );
+ OUString pastDefaultValue = extractStringProperty( past, st.DEFAULT_VALUE );
+ if( futureDefaultValue != pastDefaultValue )
+ {
+ buf.truncate();
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schemaName, tableName, settings );
+ buf.append( "ALTER COLUMN" );
+ bufferQuoteIdentifier( buf, futureColumnName, settings );
+ buf.append( "SET DEFAULT " );
+ // LEM TODO: check out
+ // default value is not quoted, caller needs to quote himself (otherwise
+ // how to pass e.g. nextval('something' ) ????
+ buf.append( futureDefaultValue );
+// bufferQuoteConstant( buf, defaultValue, encoding );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+
+ sal_Int32 futureNullable = extractIntProperty( future, st.IS_NULLABLE );
+ sal_Int32 pastNullable = extractIntProperty( past, st.IS_NULLABLE );
+ if( futureNullable != pastNullable )
+ {
+ buf.truncate();
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schemaName, tableName, settings );
+ buf.append( "ALTER COLUMN" );
+ bufferQuoteIdentifier( buf, futureColumnName, settings );
+ if( futureNullable == css::sdbc::ColumnValue::NO_NULLS )
+ {
+ buf.append( "SET" );
+ }
+ else
+ {
+ buf.append( "DROP" );
+ }
+ buf.append( " NOT NULL" );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+
+// OUString futureComment = extractStringProperty( future, st.HELP_TEXT );
+// OUString pastComment = extractStringProperty( past, st.HELP_TEXT );
+// printf( "past Comment %s, futureComment %s\n",
+// OUStringToOString( pastComment, RTL_TEXTENCODING_ASCII_US ).getStr(),
+// OUStringToOString( futureComment, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ OUString futureComment = extractStringProperty( future, st.DESCRIPTION );
+ OUString pastComment = extractStringProperty( past, st.DESCRIPTION );
+
+ if( futureComment != pastComment )
+ {
+ buf.truncate();
+ buf.append( "COMMENT ON COLUMN" );
+ bufferQuoteQualifiedIdentifier( buf, schemaName, tableName , futureColumnName, settings );
+ buf.append( "IS " );
+ bufferQuoteConstant( buf, futureComment, settings );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+ transaction.commit();
+}
+
+void Columns::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& future )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+ Reference< XPropertySet > past = createDataDescriptor();
+ past->setPropertyValue( st.IS_NULLABLE, Any( css::sdbc::ColumnValue::NULLABLE ) );
+ alterColumnByDescriptor(
+ m_schemaName, m_tableName, m_pSettings, m_origin->createStatement() , past, future );
+
+ refresh();
+}
+
+// void Columns::dropByName( const OUString& elementName )
+// throw (css::sdbc::SQLException,
+// css::container::NoSuchElementException,
+// css::uno::RuntimeException)
+// {
+// String2IntMap::const_iterator ii = m_name2index.find( elementName );
+// if( ii == m_name2index.end() )
+// {
+// OUStringBuffer buf( 128 );
+// buf.appendAscii( "Column " );
+// buf.append( elementName );
+// buf.appendAscii( " is unknown in table " );
+// buf.append( m_schemaName );
+// buf.appendAscii( "." );
+// buf.append( m_tableName );
+// buf.appendAscii( ", so it can't be dropped" );
+// throw css::container::NoSuchElementException(
+// buf.makeStringAndClear(), *this );
+// }
+// dropByIndex( ii->second );
+// }
+
+void Columns::dropByIndex( sal_Int32 index )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "COLUMNS: Index out of range (allowed 0 to "
+ + OUString::number(m_values.size() -1)
+ + ", got " + OUString::number( index ) + ")",
+ *this );
+ }
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+ Statics &st = getStatics();
+ OUString name;
+ set->getPropertyValue( st.NAME ) >>= name;
+
+ OUStringBuffer update( 128 );
+ update.append( "ALTER TABLE ONLY");
+ bufferQuoteQualifiedIdentifier( update, m_schemaName, m_tableName, m_pSettings );
+ update.append( "DROP COLUMN" );
+ bufferQuoteIdentifier( update, name, m_pSettings );
+ Reference< XStatement > stmt = m_origin->createStatement( );
+ DisposeGuard disposeIt( stmt );
+ stmt->executeUpdate( update.makeStringAndClear() );
+
+ Container::dropByIndex( index );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Columns::createDataDescriptor()
+{
+ return new ColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > Columns::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ rtl::Reference<Columns> *ppColumns)
+{
+ *ppColumns = new Columns(
+ refMutex, origin, pSettings, schemaName, tableName );
+ (*ppColumns)->refresh();
+
+ return *ppColumns;
+}
+
+
+ColumnDescriptors::ColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : Container( refMutex, origin, pSettings, "COLUMN-DESCRIPTOR" )
+{}
+
+
+Reference< css::beans::XPropertySet > ColumnDescriptors::createDataDescriptor()
+{
+ return new ColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcolumns.hxx b/connectivity/source/drivers/postgresql/pq_xcolumns.hxx
new file mode 100644
index 000000000..aa91a9754
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcolumns.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <rtl/ref.hxx>
+
+#include "pq_xcontainer.hxx"
+#include "pq_xbase.hxx"
+
+namespace com::sun::star::sdbc { class XRow; }
+
+namespace pq_sdbc_driver
+{
+
+void alterColumnByDescriptor(
+ std::u16string_view schemaName,
+ std::u16string_view tableName,
+ ConnectionSettings *settings,
+ const css::uno::Reference< css::sdbc::XStatement > &stmt,
+ const css::uno::Reference< css::beans::XPropertySet > & past,
+ const css::uno::Reference< css::beans::XPropertySet > & future);
+
+OUString columnMetaData2SDBCX(
+ ReflectionBase *pBase, const css::uno::Reference< css::sdbc::XRow > &xRow );
+
+class Columns final : public Container
+{
+ OUString m_schemaName;
+ OUString m_tableName;
+
+public: // instances Columns 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ rtl::Reference<Columns> *pColumns);
+
+private:
+ Columns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+
+ virtual ~Columns() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+// public: // XDrop
+// virtual void SAL_CALL dropByName( const OUString& elementName )
+// throw (css::sdbc::SQLException,
+// css::container::NoSuchElementException,
+// css::uno::RuntimeException);
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+
+class ColumnDescriptors : public Container
+{
+public:
+ ColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcontainer.cxx b/connectivity/source/drivers/postgresql/pq_xcontainer.cxx
new file mode 100644
index 000000000..fea88b682
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcontainer.cxx
@@ -0,0 +1,409 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xcontainer.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::RuntimeException;
+
+using com::sun::star::container::NoSuchElementException;
+using com::sun::star::container::XEnumeration;
+using com::sun::star::container::XContainerListener;
+using com::sun::star::container::ContainerEvent;
+using com::sun::star::lang::IndexOutOfBoundsException;
+using com::sun::star::lang::XEventListener;
+
+
+namespace pq_sdbc_driver
+{
+
+namespace {
+
+class ReplacedBroadcaster : public EventBroadcastHelper
+{
+ ContainerEvent m_event;
+public:
+ ReplacedBroadcaster(
+ const Reference< XInterface > & source,
+ const OUString & name,
+ const Any & newElement,
+ const OUString & oldElement ) :
+ m_event( source, Any( name ), newElement, Any(oldElement) )
+ {}
+
+ virtual void fire( XEventListener * listener ) const override
+ {
+ static_cast<XContainerListener*>(listener)->elementReplaced( m_event );
+ }
+ virtual Type getType() const override
+ {
+ return cppu::UnoType<XContainerListener>::get();
+ }
+};
+
+class InsertedBroadcaster : public EventBroadcastHelper
+{
+public:
+ ContainerEvent m_event;
+ InsertedBroadcaster(
+ const Reference< XInterface > & source,
+ const OUString & name,
+ const Any & newElement ) :
+ m_event( source, Any( name ), newElement, Any() )
+ {}
+
+ virtual void fire( XEventListener * listener ) const override
+ {
+ static_cast<XContainerListener*>(listener)->elementInserted( m_event );
+ }
+
+ virtual Type getType() const override
+ {
+ return cppu::UnoType<XContainerListener>::get();
+ }
+};
+
+class RemovedBroadcaster : public EventBroadcastHelper
+{
+public:
+ ContainerEvent m_event;
+ RemovedBroadcaster(
+ const Reference< XInterface > & source,
+ const OUString & name) :
+ m_event( source, Any( name ), Any(), Any() )
+ {}
+
+ virtual void fire( XEventListener * listener ) const override
+ {
+ static_cast<XContainerListener*>(listener)->elementRemoved( m_event );
+ }
+
+ virtual Type getType() const override
+ {
+ return cppu::UnoType<XContainerListener>::get();
+ }
+};
+
+}
+
+Container::Container(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &type)
+ : ContainerBase( refMutex->GetMutex() ),
+ m_xMutex( refMutex ),
+ m_pSettings( pSettings ),
+ m_origin( origin ),
+ m_type( type )
+{
+}
+
+Any Container::getByName( const OUString& aName )
+{
+ String2IntMap::const_iterator ii = m_name2index.find( aName );
+ if( ii == m_name2index.end() )
+ {
+ throw NoSuchElementException(
+ "Element " + aName + " unknown in " + m_type + "-Container",
+ *this );
+ }
+ OSL_ASSERT( ii->second >= 0 && o3tl::make_unsigned(ii->second) < m_values.size() );
+ return m_values[ ii->second ];
+}
+
+Sequence< OUString > Container::getElementNames( )
+{
+ Sequence< OUString > ret( m_values.size() );
+ auto retRange = asNonConstRange(ret);
+ for( const auto& [rName, rIndex] : m_name2index )
+ {
+ // give element names in index order !
+ retRange[rIndex] = rName;
+ }
+ return ret;
+}
+
+sal_Bool Container::hasByName( const OUString& aName )
+{
+ return m_name2index.find( aName ) != m_name2index.end();
+}
+ // Methods
+Type Container::getElementType( )
+{
+ return Type();
+}
+
+sal_Bool Container::hasElements( )
+{
+ return ! m_name2index.empty();
+}
+
+Any Container::getByIndex( sal_Int32 Index )
+{
+ if( Index < 0 || o3tl::make_unsigned(Index) >= m_values.size() )
+ {
+ throw IndexOutOfBoundsException(
+ "Index " + OUString::number( Index )
+ + " out of range for " + m_type + "-Container, expected 0 <= x <= "
+ + OUString::number(m_values.size() -1),
+ *this );
+ }
+ return m_values[Index];
+}
+
+sal_Int32 Container::getCount()
+{
+ return m_values.size();
+}
+
+namespace {
+
+class ContainerEnumeration : public ::cppu::WeakImplHelper< XEnumeration >
+{
+ std::vector< css::uno::Any > m_vec;
+ sal_Int32 m_index;
+public:
+ explicit ContainerEnumeration( std::vector< css::uno::Any >&& vec )
+ : m_vec( std::move(vec) ),
+ m_index( -1 )
+ {}
+
+public:
+ // XEnumeration
+ virtual sal_Bool SAL_CALL hasMoreElements( ) override;
+ virtual css::uno::Any SAL_CALL nextElement( ) override;
+
+};
+
+}
+
+sal_Bool ContainerEnumeration::hasMoreElements()
+{
+ return static_cast<int>(m_vec.size()) > m_index +1;
+}
+
+css::uno::Any ContainerEnumeration::nextElement()
+{
+ if( ! hasMoreElements() )
+ {
+ throw NoSuchElementException(
+ "NoSuchElementException during enumeration", *this );
+ }
+ m_index ++;
+ return m_vec[m_index];
+}
+
+Reference< XEnumeration > Container::createEnumeration( )
+{
+ return new ContainerEnumeration( std::vector(m_values) );
+}
+
+void Container::addRefreshListener(
+ const css::uno::Reference< css::util::XRefreshListener >& l )
+{
+ rBHelper.addListener( cppu::UnoType<decltype(l)>::get() , l );
+}
+
+void Container::removeRefreshListener(
+ const css::uno::Reference< css::util::XRefreshListener >& l )
+{
+ rBHelper.removeListener( cppu::UnoType<decltype(l)>::get() , l );
+}
+
+void Container::disposing()
+{
+ m_origin.clear();
+}
+
+void Container::rename( const OUString &oldName, const OUString &newName )
+{
+ Any newValue;
+ {
+ osl::MutexGuard guard ( m_xMutex->GetMutex() );
+ String2IntMap::iterator ii = m_name2index.find( oldName );
+ if( ii != m_name2index.end() )
+ {
+ sal_Int32 nIndex = ii->second;
+ newValue = m_values[nIndex];
+ m_name2index.erase( ii );
+ m_name2index[ newName ] = nIndex;
+ }
+ }
+ fire( ReplacedBroadcaster( *this, newName, newValue, oldName ) );
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+void Container::dropByName( const OUString& elementName )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ String2IntMap::const_iterator ii = m_name2index.find( elementName );
+ if( ii == m_name2index.end() )
+ {
+ throw css::container::NoSuchElementException(
+ "Column " + elementName + " is unknown in "
+ + m_type + " container, so it can't be dropped",
+ *this );
+ }
+ dropByIndex( ii->second );
+}
+
+void Container::dropByIndex( sal_Int32 index )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >=m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "Index out of range (allowed 0 to "
+ + OUString::number(m_values.size() -1)
+ + ", got " + OUString::number( index )
+ + ") in " + m_type,
+ *this );
+ }
+
+ OUString name;
+ String2IntMap::iterator ii = std::find_if(m_name2index.begin(), m_name2index.end(),
+ [&index](const String2IntMap::value_type& rEntry) { return rEntry.second == index; });
+ if (ii != m_name2index.end())
+ {
+ name = ii->first;
+ m_name2index.erase( ii );
+ }
+
+ for( int i = index +1 ; i < static_cast<int>(m_values.size()) ; i ++ )
+ {
+ m_values[i-1] = m_values[i];
+
+ // I know, this is expensive, but don't want to maintain another map ...
+ ii = std::find_if(m_name2index.begin(), m_name2index.end(),
+ [&i](const String2IntMap::value_type& rEntry) { return rEntry.second == i; });
+ if (ii != m_name2index.end())
+ {
+ ii->second = i-1;
+ }
+ }
+ m_values.resize( m_values.size() - 1 );
+
+ fire( RemovedBroadcaster( *this, name ) );
+}
+
+void Container::append(
+ const OUString & name,
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ if( hasByName( name ) )
+ {
+ throw css::container::ElementExistException(
+ "a " + m_type + " with name " + name + " already exists in this container",
+ *this );
+ }
+
+ int index = m_values.size();
+ m_values.push_back( Any( descriptor ) );
+ m_name2index[name] = index;
+
+ fire( InsertedBroadcaster( *this, name, Any( descriptor ) ) );
+}
+
+void Container::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor)
+{
+ append( extractStringProperty( descriptor, getStatics().NAME ), descriptor );
+}
+
+
+void Container::addContainerListener(
+ const css::uno::Reference< css::container::XContainerListener >& l )
+{
+ rBHelper.addListener( cppu::UnoType<decltype(l)>::get() , l );
+}
+
+void Container::removeContainerListener(
+ const css::uno::Reference< css::container::XContainerListener >& l )
+{
+ rBHelper.removeListener( cppu::UnoType<decltype(l)>::get() , l );
+}
+
+
+void Container::fire( const EventBroadcastHelper &helper )
+{
+ cppu::OInterfaceContainerHelper *container = rBHelper.getContainer( helper.getType() );
+ if( !container )
+ return;
+
+ cppu::OInterfaceIteratorHelper iterator( * container );
+ while( iterator.hasMoreElements() )
+ {
+ try
+ {
+ helper.fire( static_cast<XEventListener *>(iterator.next()) );
+ }
+ catch ( css::uno::RuntimeException & )
+ {
+ OSL_ENSURE( false, "exception caught" );
+ // loose coupling, a runtime exception shall not break anything
+ // TODO: log away as warning !
+ }
+ catch( css::uno::Exception & )
+ {
+ OSL_ENSURE( false, "exception from listener flying through" );
+ throw;
+ }
+ }
+
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xcontainer.hxx b/connectivity/source/drivers/postgresql/pq_xcontainer.hxx
new file mode 100644
index 000000000..fd9d432bf
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xcontainer.hxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbcx/XAppend.hpp>
+#include <com/sun/star/sdbcx/XDrop.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+
+#include <com/sun/star/util/XRefreshable.hpp>
+
+#include <comphelper/refcountedmutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <rtl/ref.hxx>
+
+#include <unordered_map>
+
+namespace pq_sdbc_driver
+{
+
+struct ConnectionSettings;
+
+class EventBroadcastHelper
+{
+public:
+ virtual void fire(css::lang::XEventListener * listener) const = 0;
+ virtual css::uno::Type getType() const = 0;
+ virtual ~EventBroadcastHelper(){};
+};
+
+class RefreshedBroadcaster : public EventBroadcastHelper
+{
+ css::lang::EventObject m_event;
+public:
+ explicit RefreshedBroadcaster(const css::uno::Reference< css::uno::XInterface > & source ) :
+ m_event( source )
+ {}
+
+ virtual void fire( css::lang::XEventListener * listener ) const override
+ {
+ static_cast<css::util::XRefreshListener*>(listener)->refreshed( m_event );
+ }
+
+ virtual css::uno::Type getType() const override
+ {
+ return cppu::UnoType<
+ css::util::XRefreshListener>::get();
+ }
+};
+
+typedef std::unordered_map
+<
+ OUString,
+ sal_Int32
+> String2IntMap;
+
+typedef ::cppu::WeakComponentImplHelper
+<
+ css::container::XNameAccess,
+ css::container::XIndexAccess,
+ css::container::XEnumerationAccess,
+ css::sdbcx::XAppend,
+ css::sdbcx::XDrop,
+ css::util::XRefreshable,
+ css::sdbcx::XDataDescriptorFactory,
+ css::container::XContainer
+> ContainerBase;
+
+class /* abstract */ Container : public ContainerBase
+{
+protected:
+ ::rtl::Reference< comphelper::RefCountedMutex > m_xMutex;
+ ConnectionSettings *m_pSettings;
+ css::uno::Reference< css::sdbc::XConnection > m_origin;
+ String2IntMap m_name2index; // maps the element name to an index
+ std::vector< css::uno::Any > m_values; // contains the real values
+ OUString m_type;
+
+public:
+ Container(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString & type // for exception messages
+ );
+
+public: // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount( ) override;
+ virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override;
+
+public: // XEnumerationAccess
+ virtual css::uno::Reference< css::container::XEnumeration >
+ SAL_CALL createEnumeration( ) override;
+
+public: // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+ // Methods
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+
+public: // XAppend
+ // Must be overridden in Non-Descriptors. May be overridden in descriptors, when
+ // PropertySet.NAME != container name
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+ // helper method !
+ /// @throws css::container::ElementExistException
+ void append(
+ const OUString & str,
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor );
+
+
+public: // XDrop
+ virtual void SAL_CALL dropByName( const OUString& elementName ) override;
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override = 0;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override {}
+ virtual void SAL_CALL addRefreshListener(
+ const css::uno::Reference< css::util::XRefreshListener >& l ) override;
+ virtual void SAL_CALL removeRefreshListener(
+ const css::uno::Reference< css::util::XRefreshListener >& l ) override;
+
+public:
+ // Methods
+ virtual void SAL_CALL addContainerListener(
+ const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener(
+ const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+public:
+ virtual void SAL_CALL disposing() override;
+
+public:
+ void rename( const OUString & oldName, const OUString &newName );
+
+protected:
+ void fire( const EventBroadcastHelper & helper );
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindex.cxx b/connectivity/source/drivers/postgresql/pq_xindex.cxx
new file mode 100644
index 000000000..5a96eeeb1
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindex.cxx
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <rtl/ref.hxx>
+
+#include "pq_xindex.hxx"
+#include "pq_xindexcolumns.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+using com::sun::star::container::XNameAccess;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::XPropertySet;
+
+
+namespace pq_sdbc_driver
+{
+Index::Index( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings,
+ const OUString & schemaName,
+ const OUString & tableName )
+ : ReflectionBase(
+ getStatics().refl.index.implName,
+ getStatics().refl.index.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.index.pProps ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName )
+{}
+
+Reference< XPropertySet > Index::createDataDescriptor( )
+{
+ rtl::Reference<IndexDescriptor> pIndex = new IndexDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pIndex->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pIndex );
+}
+
+Reference< XNameAccess > Index::getColumns( )
+{
+ if( ! m_indexColumns.is() )
+ {
+ Sequence< OUString > columnNames;
+ getPropertyValue( getStatics().PRIVATE_COLUMN_INDEXES ) >>= columnNames;
+ OUString indexName = extractStringProperty( this, getStatics().NAME );
+ m_indexColumns = IndexColumns::create(
+ m_xMutex, m_conn, m_pSettings, m_schemaName,
+ m_tableName, indexName, columnNames );
+ }
+ return m_indexColumns;
+}
+
+Sequence<Type > Index::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> Index::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any Index::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ) );
+ return ret;
+}
+
+
+IndexDescriptor::IndexDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.indexDescriptor.implName,
+ getStatics().refl.indexDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.indexDescriptor.pProps )
+{}
+
+Reference< XPropertySet > IndexDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<IndexDescriptor> pIndex = new IndexDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pIndex->copyValuesFrom( this );
+ return Reference< XPropertySet > ( pIndex );
+}
+
+Reference< XNameAccess > IndexDescriptor::getColumns( )
+{
+ if( ! m_indexColumns.is() )
+ {
+ m_indexColumns = IndexColumnDescriptors::create(
+ m_xMutex, m_conn, m_pSettings );
+// Sequence< OUString > columnNames;
+// getPropertyValue( getStatics().PRIVATE_COLUMN_INDEXES ) >>= columnNames;
+// OUString indexName = extractStringProperty( this, getStatics().NAME );
+// m_indexColumns = IndexColumns::create(
+// m_xMutex, m_conn, m_pSettings, m_schemaName,
+// m_tableName, indexName, columnNames );
+ }
+ return m_indexColumns;
+}
+
+Sequence<Type > IndexDescriptor::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> IndexDescriptor::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any IndexDescriptor::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ) );
+ return ret;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindex.hxx b/connectivity/source/drivers/postgresql/pq_xindex.hxx
new file mode 100644
index 000000000..46275ad3a
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindex.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class Index : public ReflectionBase,
+ public css::sdbcx::XColumnsSupplier
+{
+ css::uno::Reference< css::container::XNameAccess > m_indexColumns;
+
+ OUString m_schemaName;
+ OUString m_tableName;
+
+public:
+ Index( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+class IndexDescriptor : public ReflectionBase,
+ public css::sdbcx::XColumnsSupplier
+{
+ css::uno::Reference< css::container::XNameAccess > m_indexColumns;
+
+public:
+ IndexDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexcolumn.cxx b/connectivity/source/drivers/postgresql/pq_xindexcolumn.cxx
new file mode 100644
index 000000000..fe72059bc
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexcolumn.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+#include "pq_statics.hxx"
+#include "pq_xindexcolumn.hxx"
+
+using com::sun::star::uno::Reference;
+
+using com::sun::star::beans::XPropertySet;
+
+namespace pq_sdbc_driver
+{
+IndexColumn::IndexColumn( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.indexColumn.implName,
+ getStatics().refl.indexColumn.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.indexColumn.pProps )
+{}
+
+Reference< XPropertySet > IndexColumn::createDataDescriptor( )
+{
+ rtl::Reference<IndexColumnDescriptor> pIndexColumn = new IndexColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pIndexColumn->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pIndexColumn );
+}
+
+
+IndexColumnDescriptor::IndexColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.indexColumnDescriptor.implName,
+ getStatics().refl.indexColumnDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.indexColumnDescriptor.pProps )
+{}
+
+Reference< XPropertySet > IndexColumnDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<IndexColumnDescriptor> pIndexColumn = new IndexColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pIndexColumn->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pIndexColumn );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexcolumn.hxx b/connectivity/source/drivers/postgresql/pq_xindexcolumn.hxx
new file mode 100644
index 000000000..7872985ec
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexcolumn.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class IndexColumn : public ReflectionBase
+{
+public:
+ IndexColumn(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+class IndexColumnDescriptor : public ReflectionBase
+{
+public:
+ IndexColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexcolumns.cxx b/connectivity/source/drivers/postgresql/pq_xindexcolumns.cxx
new file mode 100644
index 000000000..841ea9805
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexcolumns.cxx
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+
+#include <string_view>
+#include <vector>
+
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <rtl/ref.hxx>
+
+#include "pq_xcolumns.hxx"
+#include "pq_xindexcolumns.hxx"
+#include "pq_xindexcolumn.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XDatabaseMetaData;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+IndexColumns::IndexColumns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const OUString &indexName,
+ const css::uno::Sequence< OUString > &columns )
+ : Container( refMutex, origin, pSettings, "INDEX_COLUMN" ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName ),
+ m_indexName( indexName ),
+ m_columns( columns )
+{}
+
+IndexColumns::~IndexColumns()
+{}
+
+static sal_Int32 findInSequence( const Sequence< OUString > & seq , std::u16string_view str)
+{
+ int index;
+ for( index = 0 ; index < seq.getLength() ; index ++ )
+ {
+ if( str == seq[index] )
+ break;
+ }
+ return index;
+}
+
+void IndexColumns::refresh()
+{
+ try
+ {
+ SAL_INFO("connectivity.postgresql", "sdbcx.IndexColumns get refreshed for index " << m_indexName);
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ Statics &st = getStatics();
+ Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
+
+ Reference< XResultSet > rs =
+ meta->getColumns( Any(), m_schemaName, m_tableName, st.cPERCENT );
+
+ DisposeGuard disposeIt( rs );
+ Reference< XRow > xRow( rs , UNO_QUERY );
+ m_values.clear();
+ m_values.resize( m_columns.getLength() );
+
+ while( rs->next() )
+ {
+ OUString columnName = xRow->getString( 4 );
+
+ sal_Int32 index = findInSequence( m_columns, columnName );
+ if( index >= m_columns.getLength() )
+ continue;
+
+ rtl::Reference<IndexColumn> pIndexColumn =
+ new IndexColumn( m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pIndexColumn;
+
+ columnMetaData2SDBCX( pIndexColumn.get(), xRow );
+ pIndexColumn->setPropertyValue_NoBroadcast_public(
+ st.IS_ASCENDING , Any( false ) );
+
+ m_values[ index ] <<= prop;
+ m_name2index[ columnName ] = index;
+ }
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void IndexColumns::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& /*future*/ )
+{
+ throw css::sdbc::SQLException(
+ "SDBC-POSTGRESQL: IndexesColumns.appendByDescriptor not yet implemented",
+ *this, OUString(), 1, Any() );
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// Statics & st = getStatics();
+// Reference< XPropertySet > past = createDataDescriptor();
+// past->setPropertyValue( st.IS_NULLABLE, makeAny( css::sdbc::ColumnValue::NULLABLE ) );
+// alterColumnByDescriptor(
+// m_schemaName, m_tableName, m_pSettings->encoding, m_origin->createStatement() , past, future );
+
+}
+
+void IndexColumns::dropByName( const OUString& )
+{
+ throw css::sdbc::SQLException(
+ "SDBC-POSTGRESQL: IndexesColumns.dropByName not yet implemented",
+ *this, OUString(), 1, Any() );
+// String2IntMap::const_iterator ii = m_name2index.find( elementName );
+// if( ii == m_name2index.end() )
+// {
+// OUStringBuffer buf( 128 );
+// buf.appendAscii( "Column " );
+// buf.append( elementName );
+// buf.appendAscii( " is unknown in table " );
+// buf.append( m_schemaName );
+// buf.appendAscii( "." );
+// buf.append( m_tableName );
+// buf.appendAscii( ", so it can't be dropped" );
+// throw css::container::NoSuchElementException(
+// buf.makeStringAndClear(), *this );
+// }
+// dropByIndex( ii->second );
+}
+
+void IndexColumns::dropByIndex( sal_Int32 )
+{
+ throw css::sdbc::SQLException(
+ "SDBC-POSTGRESQL: IndexesColumns.dropByIndex not yet implemented",
+ *this, OUString(), 1, Any() );
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// if( index < 0 || index >= m_values.getLength() )
+// {
+// OUStringBuffer buf( 128 );
+// buf.appendAscii( "COLUMNS: Index out of range (allowed 0 to " );
+// buf.append((sal_Int32)(m_values.getLength() -1) );
+// buf.appendAscii( ", got " );
+// buf.append( index );
+// buf.appendAscii( ")" );
+// throw css::lang::IndexOutOfBoundsException(
+// buf.makeStringAndClear(), *this );
+// }
+
+// Reference< XPropertySet > set;
+// m_values[index] >>= set;
+// Statics &st = getStatics();
+// OUString name;
+// set->getPropertyValue( st.NAME ) >>= name;
+
+// OUStringBuffer update( 128 );
+// update.appendAscii( "ALTER TABLE ONLY");
+// bufferQuoteQualifiedIdentifier( update, m_schemaName, m_tableName );
+// update.appendAscii( "DROP COLUMN" );
+// bufferQuoteIdentifier( update, name );
+// Reference< XStatement > stmt = m_origin->createStatement( );
+// DisposeGuard disposeIt( stmt );
+// stmt->executeUpdate( update.makeStringAndClear() );
+
+}
+
+
+Reference< css::beans::XPropertySet > IndexColumns::createDataDescriptor()
+{
+ return new IndexColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > IndexColumns::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const OUString &indexName,
+ const Sequence< OUString > &columns )
+{
+ rtl::Reference<IndexColumns> pIndexColumns = new IndexColumns(
+ refMutex, origin, pSettings, schemaName, tableName, indexName, columns );
+ pIndexColumns->refresh();
+
+ return pIndexColumns;
+}
+
+
+IndexColumnDescriptors::IndexColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+ : Container( refMutex, origin, pSettings, getStatics().INDEX_COLUMN )
+{}
+
+Reference< css::container::XNameAccess > IndexColumnDescriptors::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+{
+ return new IndexColumnDescriptors( refMutex, origin, pSettings );
+}
+
+css::uno::Reference< css::beans::XPropertySet > IndexColumnDescriptors::createDataDescriptor()
+{
+ return new IndexColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexcolumns.hxx b/connectivity/source/drivers/postgresql/pq_xindexcolumns.hxx
new file mode 100644
index 000000000..eaaa709e6
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexcolumns.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class IndexColumns final : public Container
+{
+ OUString m_schemaName;
+ OUString m_tableName;
+ OUString m_indexName;
+ css::uno::Sequence< OUString > m_columns;
+
+public: // instances IndexColumns 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const OUString &indexName,
+ const css::uno::Sequence< OUString > &columns );
+
+private:
+ IndexColumns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const OUString &indexName,
+ const css::uno::Sequence< OUString > &columns );
+
+ virtual ~IndexColumns() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+ virtual void SAL_CALL dropByName( const OUString& elementName ) override;
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+
+class IndexColumnDescriptors final : public Container
+{
+
+public: // instances IndexColumns 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+private:
+ IndexColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexes.cxx b/connectivity/source/drivers/postgresql/pq_xindexes.cxx
new file mode 100644
index 000000000..ef1e7116a
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexes.cxx
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xindexes.hxx"
+#include "pq_xindex.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+
+using com::sun::star::container::XEnumerationAccess;
+using com::sun::star::container::XEnumeration;
+
+
+using com::sun::star::sdbcx::XColumnsSupplier;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XParameters;
+using com::sun::star::sdbc::XPreparedStatement;
+
+namespace pq_sdbc_driver
+{
+
+Indexes::Indexes(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName)
+ : Container( refMutex, origin, pSettings, getStatics().KEY ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName )
+{
+}
+
+Indexes::~Indexes()
+{}
+
+void Indexes::refresh()
+{
+ try
+ {
+ SAL_INFO("connectivity.postgresql", "sdbcx.Indexes get refreshed for table " << m_schemaName << "." << m_tableName);
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ Int2StringMap column2NameMap;
+ fillAttnum2attnameMap( column2NameMap, m_origin, m_schemaName, m_tableName );
+
+ // see XDatabaseMetaData::getIndexInfo()
+ Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
+ "SELECT nspname, " // 1
+ "pg_class.relname, " // 2
+ "class2.relname, " // 3
+ "indisclustered, " // 4
+ "indisunique, " // 5
+ "indisprimary, " // 6
+ "indkey " // 7
+ "FROM pg_index INNER JOIN pg_class ON indrelid = pg_class.oid "
+ "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
+ "INNER JOIN pg_class as class2 ON pg_index.indexrelid = class2.oid "
+ "WHERE nspname = ? AND pg_class.relname = ?" );
+
+ Reference< XParameters > params( stmt, UNO_QUERY);
+ params->setString( 1, m_schemaName );
+ params->setString( 2, m_tableName );
+ Reference< XResultSet > rs = stmt->executeQuery();
+
+ Reference< XRow > row( rs, UNO_QUERY );
+ String2IntMap map;
+ m_values.clear();
+ sal_Int32 index = 0;
+ while( rs->next() )
+ {
+ // C_SCHEMA = 1
+ // C_TABLENAME = 2
+ static const sal_Int32 C_INDEXNAME = 3;
+ static const sal_Int32 C_IS_CLUSTERED = 4;
+ static const sal_Int32 C_IS_UNIQUE = 5;
+ static const sal_Int32 C_IS_PRIMARY = 6;
+ static const sal_Int32 C_COLUMNS = 7;
+ OUString currentIndexName = row->getString( C_INDEXNAME );
+ rtl::Reference<Index> pIndex =
+ new Index( m_xMutex, m_origin, m_pSettings,
+ m_schemaName, m_tableName );
+
+ bool isUnique = row->getBoolean( C_IS_UNIQUE );
+ bool isPrimary = row->getBoolean( C_IS_PRIMARY );
+ bool isClusterd = row->getBoolean( C_IS_CLUSTERED );
+ Reference< css::beans::XPropertySet > prop = pIndex;
+ pIndex->setPropertyValue_NoBroadcast_public(
+ st.IS_UNIQUE, Any( isUnique ) );
+ pIndex->setPropertyValue_NoBroadcast_public(
+ st.IS_PRIMARY_KEY_INDEX, Any( isPrimary ) );
+ pIndex->setPropertyValue_NoBroadcast_public(
+ st.IS_CLUSTERED, Any( isClusterd ) );
+ pIndex->setPropertyValue_NoBroadcast_public(
+ st.NAME, Any( currentIndexName ) );
+
+ std::vector< sal_Int32 > seq = parseIntArray( row->getString( C_COLUMNS ) );
+ Sequence< OUString > columnNames(seq.size());
+ auto columnNamesRange = asNonConstRange(columnNames);
+ for( size_t columns = 0 ; columns < seq.size() ; columns ++ )
+ {
+ columnNamesRange[columns] = column2NameMap[ seq[columns] ];
+ }
+
+ pIndex->setPropertyValue_NoBroadcast_public(
+ st.PRIVATE_COLUMN_INDEXES, Any( columnNames ));
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ currentIndexName ] = index;
+ ++index;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void Indexes::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ Statics & st = getStatics();
+ OUString name = extractStringProperty( descriptor, st.NAME );
+
+ bool isUnique = extractBoolProperty( descriptor, st.IS_UNIQUE );
+
+ OUStringBuffer buf( 128 );
+
+ buf.append( "CREATE " );
+ if( isUnique )
+ buf.append( "UNIQUE " );
+ buf.append( "INDEX " );
+ bufferQuoteIdentifier( buf, name, m_pSettings );
+ buf.append( " ON " );
+ bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
+
+ buf.append( " ( " );
+
+ Reference< XColumnsSupplier > columns( descriptor, UNO_QUERY );
+ if( columns.is() )
+ {
+ Reference< XEnumerationAccess > access( columns->getColumns(), UNO_QUERY );
+ if( access.is() )
+ {
+ Reference< XEnumeration > xEnum( access->createEnumeration() );
+ bool first = true;
+ while( xEnum.is() && xEnum->hasMoreElements() )
+ {
+ Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
+ if( first )
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append( ", " );
+ }
+ buf.append( extractStringProperty( column, st.NAME ) );
+ }
+ }
+ }
+ buf.append( " ) " );
+
+ m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
+ refresh();
+}
+
+void Indexes::dropByIndex( sal_Int32 index )
+{
+
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "Indexes: Index out of range (allowed 0 to "
+ + OUString::number( m_values.size() -1 )
+ + ", got " + OUString::number( index )
+ + ")",
+ *this );
+ }
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+ Statics &st = getStatics();
+
+ OUStringBuffer buf( 128 );
+ buf.append( "DROP INDEX " );
+ bufferQuoteIdentifier( buf, extractStringProperty( set, st.NAME ), m_pSettings );
+ m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
+
+ Container::dropByIndex( index );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Indexes::createDataDescriptor()
+{
+ return new IndexDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > Indexes::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString & schemaName,
+ const OUString & tableName)
+{
+ rtl::Reference<Indexes> pIndexes
+ = new Indexes( refMutex, origin, pSettings, schemaName, tableName );
+ pIndexes->refresh();
+ return pIndexes;
+}
+
+
+IndexDescriptors::IndexDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+ : Container( refMutex, origin, pSettings, getStatics().INDEX )
+{}
+
+Reference< css::container::XNameAccess > IndexDescriptors::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+{
+ return new IndexDescriptors( refMutex, origin, pSettings );
+}
+
+css::uno::Reference< css::beans::XPropertySet > IndexDescriptors::createDataDescriptor()
+{
+ return new IndexDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xindexes.hxx b/connectivity/source/drivers/postgresql/pq_xindexes.hxx
new file mode 100644
index 000000000..c2e81f617
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xindexes.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+class Indexes final : public Container
+{
+ OUString m_schemaName;
+ OUString m_tableName;
+
+public: // instances Columns 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+private:
+ Indexes(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+ virtual ~Indexes() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+
+class IndexDescriptors final : public Container
+{
+public: // instances IndexDescriptors 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+private:
+ IndexDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkey.cxx b/connectivity/source/drivers/postgresql/pq_xkey.cxx
new file mode 100644
index 000000000..e27778245
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkey.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <rtl/ref.hxx>
+
+#include "pq_xkey.hxx"
+#include "pq_xkeycolumns.hxx"
+#include "pq_statics.hxx"
+
+using com::sun::star::container::XNameAccess;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::XPropertySet;
+
+
+namespace pq_sdbc_driver
+{
+Key::Key( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings,
+ const OUString & schemaName,
+ const OUString & tableName )
+ : ReflectionBase(
+ getStatics().refl.key.implName,
+ getStatics().refl.key.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.key.pProps ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName )
+{}
+
+Reference< XPropertySet > Key::createDataDescriptor( )
+{
+ rtl::Reference<KeyDescriptor> pKeyDescriptor = new KeyDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pKeyDescriptor->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pKeyDescriptor );
+}
+
+Reference< XNameAccess > Key::getColumns( )
+{
+ // TODO: cash columns object !
+ if( !m_keyColumns.is() )
+ {
+ Sequence< OUString > columnNames, foreignColumnNames;
+ getPropertyValue( getStatics().PRIVATE_COLUMNS ) >>= columnNames;
+ getPropertyValue( getStatics().PRIVATE_FOREIGN_COLUMNS ) >>= foreignColumnNames;
+
+ m_keyColumns = KeyColumns::create(
+ m_xMutex, m_conn, m_pSettings, m_schemaName,
+ m_tableName, columnNames, foreignColumnNames );
+ }
+ return m_keyColumns;
+}
+
+Sequence<Type > Key::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> Key::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any Key::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ) );
+ return ret;
+}
+
+
+KeyDescriptor::KeyDescriptor( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.keyDescriptor.implName,
+ getStatics().refl.keyDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.keyDescriptor.pProps )
+{
+}
+
+Reference< XPropertySet > KeyDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<KeyDescriptor> pKeyDescriptor = new KeyDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pKeyDescriptor->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pKeyDescriptor );
+}
+
+Reference< XNameAccess > KeyDescriptor::getColumns( )
+{
+ // TODO: cash columns object !
+ if( !m_keyColumns.is() )
+ {
+ m_keyColumns = new KeyColumnDescriptors( m_xMutex, m_conn, m_pSettings );
+ }
+ return m_keyColumns;
+}
+
+Sequence<Type > KeyDescriptor::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> KeyDescriptor::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any KeyDescriptor::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ) );
+ return ret;
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkey.hxx b/connectivity/source/drivers/postgresql/pq_xkey.hxx
new file mode 100644
index 000000000..d231e1e89
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkey.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class Key : public ReflectionBase,
+ public css::sdbcx::XColumnsSupplier
+{
+ css::uno::Reference< css::container::XNameAccess > m_keyColumns;
+
+ OUString m_schemaName;
+ OUString m_tableName;
+
+public:
+ Key( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+class KeyDescriptor : public ReflectionBase, public css::sdbcx::XColumnsSupplier
+{
+ css::uno::Reference< css::container::XNameAccess > m_keyColumns;
+
+public:
+ KeyDescriptor( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings );
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+};
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeycolumn.cxx b/connectivity/source/drivers/postgresql/pq_xkeycolumn.cxx
new file mode 100644
index 000000000..30eef1797
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeycolumn.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+#include "pq_statics.hxx"
+#include "pq_xkeycolumn.hxx"
+
+using com::sun::star::uno::Reference;
+
+using com::sun::star::beans::XPropertySet;
+
+namespace pq_sdbc_driver
+{
+KeyColumn::KeyColumn( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.keycolumn.implName,
+ getStatics().refl.keycolumn.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.keycolumn.pProps )
+{}
+
+Reference< XPropertySet > KeyColumn::createDataDescriptor( )
+{
+ rtl::Reference<KeyColumnDescriptor> pKeyColumn = new KeyColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pKeyColumn->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pKeyColumn );
+}
+
+KeyColumnDescriptor::KeyColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.keycolumnDescriptor.implName,
+ getStatics().refl.keycolumnDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.keycolumnDescriptor.pProps )
+{}
+
+Reference< XPropertySet > KeyColumnDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<KeyColumnDescriptor> pKeyColumn = new KeyColumnDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pKeyColumn->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pKeyColumn );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeycolumn.hxx b/connectivity/source/drivers/postgresql/pq_xkeycolumn.hxx
new file mode 100644
index 000000000..7d49d5d26
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeycolumn.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <cppuhelper/component.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
+
+#include "pq_connection.hxx"
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class KeyColumn : public ReflectionBase
+{
+public:
+ KeyColumn( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+class KeyColumnDescriptor : public ReflectionBase
+{
+public:
+ KeyColumnDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+};
+
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeycolumns.cxx b/connectivity/source/drivers/postgresql/pq_xkeycolumns.cxx
new file mode 100644
index 000000000..8b62f2842
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeycolumns.cxx
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <rtl/ref.hxx>
+
+#include "pq_xcolumns.hxx"
+#include "pq_xkeycolumns.hxx"
+#include "pq_xkeycolumn.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XDatabaseMetaData;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+KeyColumns::KeyColumns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const Sequence< OUString > &columnNames,
+ const Sequence< OUString > &foreignColumnNames )
+ : Container( refMutex, origin, pSettings, "KEY_COLUMN" ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName ),
+ m_columnNames( columnNames ),
+ m_foreignColumnNames( foreignColumnNames )
+{}
+
+KeyColumns::~KeyColumns()
+{}
+
+
+void KeyColumns::refresh()
+{
+ try
+ {
+ SAL_INFO("connectivity.postgresql", "sdbcx.KeyColumns get refreshed for table " << m_schemaName << "." << m_tableName);
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ Statics &st = getStatics();
+ Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
+
+ Reference< XResultSet > rs =
+ meta->getColumns( Any(), m_schemaName, m_tableName, st.cPERCENT );
+
+ DisposeGuard disposeIt( rs );
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ String2IntMap map;
+
+ m_values.clear();
+ sal_Int32 columnIndex = 0;
+ while( rs->next() )
+ {
+ OUString columnName = xRow->getString( 4 );
+
+ int keyindex;
+ for( keyindex = 0 ; keyindex < m_columnNames.getLength() ; keyindex ++ )
+ {
+ if( columnName == m_columnNames[keyindex] )
+ break;
+ }
+ if( m_columnNames.getLength() == keyindex )
+ continue;
+
+ rtl::Reference<KeyColumn> pKeyColumn =
+ new KeyColumn( m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pKeyColumn;
+
+ OUString name = columnMetaData2SDBCX( pKeyColumn.get(), xRow );
+ if( keyindex < m_foreignColumnNames.getLength() )
+ {
+ pKeyColumn->setPropertyValue_NoBroadcast_public(
+ st.RELATED_COLUMN, Any( m_foreignColumnNames[keyindex]) );
+ }
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ name ] = columnIndex;
+ ++columnIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void KeyColumns::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& )
+{
+ throw css::sdbc::SQLException(
+ "KeyColumns::appendByDescriptor not implemented yet",
+ *this, OUString(), 1, Any() );
+
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// Statics & st = getStatics();
+// Reference< XPropertySet > past = createDataDescriptor();
+// past->setPropertyValue( st.IS_NULLABLE, makeAny( css::sdbc::ColumnValue::NULLABLE ) );
+// alterColumnByDescriptor(
+// m_schemaName, m_tableName, m_pSettings->encoding, m_origin->createStatement() , past, future );
+
+}
+
+
+void KeyColumns::dropByIndex( sal_Int32 )
+{
+ throw css::sdbc::SQLException(
+ "KeyColumns::dropByIndex not implemented yet",
+ *this, OUString(), 1, Any() );
+// osl::MutexGuard guard( m_xMutex->GetMutex() );
+// if( index < 0 || index >= m_values.getLength() )
+// {
+// OUStringBuffer buf( 128 );
+// buf.appendAscii( "COLUMNS: Index out of range (allowed 0 to " );
+// buf.append((sal_Int32)(m_values.getLength() -1) );
+// buf.appendAscii( ", got " );
+// buf.append( index );
+// buf.appendAscii( ")" );
+// throw css::lang::IndexOutOfBoundsException(
+// buf.makeStringAndClear(), *this );
+// }
+
+// Reference< XPropertySet > set;
+// m_values[index] >>= set;
+// Statics &st = getStatics();
+// OUString name;
+// set->getPropertyValue( st.NAME ) >>= name;
+
+// OUStringBuffer update( 128 );
+// update.appendAscii( "ALTER TABLE ONLY");
+// bufferQuoteQualifiedIdentifier( update, m_schemaName, m_tableName );
+// update.appendAscii( "DROP COLUMN" );
+// bufferQuoteIdentifier( update, name );
+// Reference< XStatement > stmt = m_origin->createStatement( );
+// DisposeGuard disposeIt( stmt );
+// stmt->executeUpdate( update.makeStringAndClear() );
+
+}
+
+
+Reference< css::beans::XPropertySet > KeyColumns::createDataDescriptor()
+{
+ return new KeyColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > KeyColumns::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const Sequence< OUString > &columnNames ,
+ const Sequence< OUString > &foreignColumnNames )
+{
+ rtl::Reference<KeyColumns> pKeyColumns = new KeyColumns(
+ refMutex, origin, pSettings, schemaName, tableName, columnNames, foreignColumnNames );
+ pKeyColumns->refresh();
+
+ return pKeyColumns;
+}
+
+
+KeyColumnDescriptors::KeyColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : Container( refMutex, origin, pSettings, "KEY_COLUMN" )
+{}
+
+Reference< css::beans::XPropertySet > KeyColumnDescriptors::createDataDescriptor()
+{
+ return new KeyColumnDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeycolumns.hxx b/connectivity/source/drivers/postgresql/pq_xkeycolumns.hxx
new file mode 100644
index 000000000..0c56fd189
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeycolumns.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class KeyColumns final : public Container
+{
+ OUString m_schemaName;
+ OUString m_tableName;
+ css::uno::Sequence< OUString > m_columnNames;
+ css::uno::Sequence< OUString > m_foreignColumnNames;
+
+public: // instances KeyColumns 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const css::uno::Sequence< OUString > &keyColumns,
+ const css::uno::Sequence< OUString > &foreignColumnNames );
+
+private:
+ KeyColumns(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName,
+ const css::uno::Sequence< OUString > &keyColumns,
+ const css::uno::Sequence< OUString > &foreignColumnNames);
+
+ virtual ~KeyColumns() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+
+class KeyColumnDescriptors : public Container
+{
+public:
+ KeyColumnDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeys.cxx b/connectivity/source/drivers/postgresql/pq_xkeys.cxx
new file mode 100644
index 000000000..dced2bc9b
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeys.cxx
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/KeyRule.hpp>
+#include <com/sun/star/sdbcx/KeyType.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xkeys.hxx"
+#include "pq_xkey.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+
+using css::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XParameters;
+using com::sun::star::sdbc::XPreparedStatement;
+
+namespace pq_sdbc_driver
+{
+
+Keys::Keys(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName)
+ : Container( refMutex, origin, pSettings, getStatics().KEY ),
+ m_schemaName( schemaName ),
+ m_tableName( tableName )
+{}
+
+Keys::~Keys()
+{}
+
+static sal_Int32 string2keytype( std::u16string_view type )
+{
+ sal_Int32 ret = css::sdbcx::KeyType::UNIQUE;
+ if ( type == u"p" )
+ ret = css::sdbcx::KeyType::PRIMARY;
+ else if ( type == u"f" )
+ ret = css::sdbcx::KeyType::FOREIGN;
+ return ret;
+}
+
+static sal_Int32 string2keyrule( std::u16string_view rule )
+{
+ sal_Int32 ret = css::sdbc::KeyRule::NO_ACTION;
+ if( rule == u"r" )
+ ret = css::sdbc::KeyRule::RESTRICT;
+ else if( rule == u"c" )
+ ret = css::sdbc::KeyRule::CASCADE;
+ else if( rule == u"n" )
+ ret = css::sdbc::KeyRule::SET_NULL;
+ else if( rule == u"d" )
+ ret = css::sdbc::KeyRule::SET_DEFAULT;
+ return ret;
+}
+
+void Keys::refresh()
+{
+ try
+ {
+ SAL_INFO("connectivity.postgresql", "sdbcx.Keys get refreshed for table " << m_schemaName << "." << m_tableName);
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ Int2StringMap mainMap;
+ fillAttnum2attnameMap( mainMap, m_origin, m_schemaName, m_tableName );
+
+ Reference< XPreparedStatement > stmt = m_origin->prepareStatement(
+ "SELECT conname, " // 1
+ "contype, " // 2
+ "confupdtype, " // 3
+ "confdeltype, " // 4
+ "class2.relname, " // 5
+ "nmsp2.nspname, " // 6
+ "conkey," // 7
+ "confkey " // 8
+ "FROM pg_constraint INNER JOIN pg_class ON conrelid = pg_class.oid "
+ "INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid "
+ "LEFT JOIN pg_class AS class2 ON confrelid = class2.oid "
+ "LEFT JOIN pg_namespace AS nmsp2 ON class2.relnamespace=nmsp2.oid "
+ "WHERE pg_class.relname = ? AND pg_namespace.nspname = ?" );
+
+ Reference< XParameters > paras( stmt, UNO_QUERY );
+ paras->setString( 1 , m_tableName );
+ paras->setString( 2 , m_schemaName );
+ Reference< XResultSet > rs = stmt->executeQuery();
+
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ String2IntMap map;
+ m_values.clear();
+ int keyIndex = 0;
+ while( rs->next() )
+ {
+ rtl::Reference<Key> pKey =
+ new Key( m_xMutex, m_origin, m_pSettings , m_schemaName, m_tableName );
+ Reference< css::beans::XPropertySet > prop = pKey;
+
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.NAME, Any( xRow->getString( 1 ) ) );
+ sal_Int32 keyType = string2keytype( xRow->getString(2) );
+ pKey->setPropertyValue_NoBroadcast_public( st.TYPE, Any( keyType ) );
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.UPDATE_RULE, Any( string2keyrule( xRow->getString(3) ) ) );
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.DELETE_RULE, Any( string2keyrule( xRow->getString(4) ) ) );
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.PRIVATE_COLUMNS,
+ Any(
+ convertMappedIntArray2StringArray(
+ mainMap,
+ string2intarray( xRow->getString( 7 ) ) ) ) );
+
+ if( css::sdbcx::KeyType::FOREIGN == keyType )
+ {
+ OUString buf = xRow->getString( 6 ) + "." + xRow->getString( 5 );
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.REFERENCED_TABLE, Any( buf ) );
+
+ Int2StringMap foreignMap;
+ fillAttnum2attnameMap( foreignMap, m_origin, xRow->getString(6), xRow->getString(5));
+ pKey->setPropertyValue_NoBroadcast_public(
+ st.PRIVATE_FOREIGN_COLUMNS,
+ Any(
+ convertMappedIntArray2StringArray(
+ foreignMap,
+ string2intarray( xRow->getString(8) ) ) ) );
+ }
+
+
+ {
+ map[ xRow->getString( 1 ) ] = keyIndex;
+ m_values.push_back( Any( prop ) );
+ ++keyIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void Keys::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ OUStringBuffer buf( 128 );
+ buf.append( "ALTER TABLE " );
+ bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
+ buf.append( " ADD " );
+ bufferKey2TableConstraint( buf, descriptor, m_pSettings );
+
+ Reference< XStatement > stmt =
+ m_origin->createStatement();
+ stmt->executeUpdate( buf.makeStringAndClear() );
+}
+
+
+void Keys::dropByIndex( sal_Int32 index )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "TABLES: Index out of range (allowed 0 to " + OUString::number(m_values.size() -1)
+ + ", got " + OUString::number( index ) + ")",
+ *this );
+ }
+
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+
+ OUStringBuffer buf( 128 );
+ buf.append( "ALTER TABLE " );
+ bufferQuoteQualifiedIdentifier( buf, m_schemaName, m_tableName, m_pSettings );
+ buf.append( " DROP CONSTRAINT " );
+ bufferQuoteIdentifier( buf, extractStringProperty( set , getStatics().NAME ), m_pSettings );
+ m_origin->createStatement()->executeUpdate( buf.makeStringAndClear() );
+
+
+ Container::dropByIndex( index );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Keys::createDataDescriptor()
+{
+ return new KeyDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XIndexAccess > Keys::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString & schemaName,
+ const OUString & tableName)
+{
+ rtl::Reference<Keys> pKeys = new Keys( refMutex, origin, pSettings, schemaName, tableName );
+ pKeys->refresh();
+
+ return pKeys;
+}
+
+KeyDescriptors::KeyDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+ : Container( refMutex, origin, pSettings, getStatics().KEY )
+{}
+
+Reference< css::container::XIndexAccess > KeyDescriptors::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings)
+{
+ return new KeyDescriptors( refMutex, origin, pSettings );
+}
+
+css::uno::Reference< css::beans::XPropertySet > KeyDescriptors::createDataDescriptor()
+{
+ return new KeyDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xkeys.hxx b/connectivity/source/drivers/postgresql/pq_xkeys.hxx
new file mode 100644
index 000000000..fe1afef35
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xkeys.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+class Keys final : public Container
+{
+ OUString m_schemaName;
+ OUString m_tableName;
+
+public: // instances Columns 'exception safe'
+ static css::uno::Reference< css::container::XIndexAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+private:
+ Keys(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ const OUString &schemaName,
+ const OUString &tableName);
+
+ virtual ~Keys() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+
+class KeyDescriptors final : public Container
+{
+public: // instances Columns 'exception safe'
+ static css::uno::Reference< css::container::XIndexAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+private:
+ KeyDescriptors(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xtable.cxx b/connectivity/source/drivers/postgresql/pq_xtable.cxx
new file mode 100644
index 000000000..4a659ffb9
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xtable.cxx
@@ -0,0 +1,394 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include "pq_xtable.hxx"
+#include "pq_xtables.hxx"
+#include "pq_xviews.hxx"
+#include "pq_xindexes.hxx"
+#include "pq_xkeys.hxx"
+#include "pq_xcolumns.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::container::XNameAccess;
+using com::sun::star::container::XIndexAccess;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+Table::Table( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.table.implName,
+ getStatics().refl.table.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.table.pProps )
+{}
+
+Reference< XPropertySet > Table::createDataDescriptor( )
+{
+ rtl::Reference<TableDescriptor> pTable = new TableDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pTable->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pTable );
+}
+
+Reference< XNameAccess > Table::getColumns( )
+{
+ if( ! m_columns.is() )
+ {
+ m_columns = Columns::create(
+ m_xMutex,
+ m_conn,
+ m_pSettings,
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ),
+ &m_pColumns);
+ }
+ return m_columns;
+}
+
+Reference< XNameAccess > Table::getIndexes()
+{
+ if( ! m_indexes.is() )
+ {
+ m_indexes = ::pq_sdbc_driver::Indexes::create(
+ m_xMutex,
+ m_conn,
+ m_pSettings,
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ) );
+ }
+ return m_indexes;
+}
+
+Reference< XIndexAccess > Table::getKeys( )
+{
+ if( ! m_keys.is() )
+ {
+ m_keys = ::pq_sdbc_driver::Keys::create(
+ m_xMutex,
+ m_conn,
+ m_pSettings,
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ) );
+ }
+ return m_keys;
+}
+
+void Table::rename( const OUString& newName )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ OUString oldName = extractStringProperty(this,st.NAME );
+ OUString schema = extractStringProperty(this,st.SCHEMA_NAME );
+ OUString fullOldName = concatQualified( schema, oldName );
+
+ OUString newTableName;
+ OUString newSchemaName;
+ // OOo2.0 passes schema + dot + new-table-name while
+ // OO1.1.x passes new Name without schema
+ // in case name contains a dot, it is interpreted as schema.tablename
+ if( newName.indexOf( '.' ) >= 0 )
+ {
+ splitConcatenatedIdentifier( newName, &newSchemaName, &newTableName );
+ }
+ else
+ {
+ newTableName = newName;
+ newSchemaName = schema;
+ }
+ OUString fullNewName = concatQualified( newSchemaName, newTableName );
+
+ if( extractStringProperty( this, st.TYPE ) == st.VIEW && m_pSettings->views.is() )
+ {
+ // maintain view list (really strange API !)
+ Any a = m_pSettings->pViewsImpl->getByName( fullOldName );
+ Reference< css::sdbcx::XRename > Xrename;
+ a >>= Xrename;
+ if( Xrename.is() )
+ {
+ Xrename->rename( newName );
+ setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME, Any(newSchemaName) );
+ }
+ }
+ else
+ {
+ if( newSchemaName != schema )
+ {
+ // try new schema name first
+ try
+ {
+ OUStringBuffer buf(128);
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier(buf, schema, oldName, m_pSettings );
+ buf.append( "SET SCHEMA" );
+ bufferQuoteIdentifier( buf, newSchemaName, m_pSettings );
+ Reference< XStatement > statement = m_conn->createStatement();
+ statement->executeUpdate( buf.makeStringAndClear() );
+ setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME, Any(newSchemaName) );
+ disposeNoThrow( statement );
+ schema = newSchemaName;
+ }
+ catch( css::sdbc::SQLException &e )
+ {
+ OUString buf( e.Message + "(NOTE: Only postgresql server >= V8.1 support changing a table's schema)" );
+ e.Message = buf;
+ throw;
+ }
+
+ }
+ if( newTableName != oldName ) // might also be just the change of a schema name
+ {
+ OUStringBuffer buf(128);
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier(buf, schema, oldName, m_pSettings );
+ buf.append( "RENAME TO" );
+ bufferQuoteIdentifier( buf, newTableName, m_pSettings );
+ Reference< XStatement > statement = m_conn->createStatement();
+ statement->executeUpdate( buf.makeStringAndClear() );
+ disposeNoThrow( statement );
+ }
+ }
+ setPropertyValue_NoBroadcast_public( st.NAME, Any(newTableName) );
+ // inform the container of the name change !
+ if( m_pSettings->tables.is() )
+ {
+ m_pSettings->pTablesImpl->rename( fullOldName, fullNewName );
+ }
+}
+
+void Table::alterColumnByName(
+ const OUString& colName,
+ const Reference< XPropertySet >& descriptor )
+{
+ Reference< css::container::XNameAccess > columns = getColumns();
+
+ OUString newName = extractStringProperty(descriptor, getStatics().NAME );
+ ::pq_sdbc_driver::alterColumnByDescriptor(
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ),
+ m_pSettings,
+ m_conn->createStatement(),
+ Reference< css::beans::XPropertySet>( columns->getByName( colName ), UNO_QUERY) ,
+ descriptor );
+
+ if( colName != newName )
+ {
+// m_pColumns->rename( colName, newName );
+ m_pColumns->refresh();
+ }
+}
+
+void Table::alterColumnByIndex(
+ sal_Int32 index,
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ Reference< css::container::XIndexAccess > columns( getColumns(), UNO_QUERY );
+ Reference< css::beans::XPropertySet> column(columns->getByIndex( index ), UNO_QUERY );
+ ::pq_sdbc_driver::alterColumnByDescriptor(
+ extractStringProperty( this, getStatics().SCHEMA_NAME ),
+ extractStringProperty( this, getStatics().NAME ),
+ m_pSettings,
+ m_conn->createStatement(),
+ column,
+ descriptor );
+ m_pColumns->refresh();
+}
+
+Sequence<Type > Table::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XIndexesSupplier>::get(),
+ cppu::UnoType<css::sdbcx::XKeysSupplier>::get(),
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ cppu::UnoType<css::sdbcx::XRename>::get(),
+ cppu::UnoType<css::sdbcx::XAlterTable>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> Table::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any Table::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XIndexesSupplier * > ( this ),
+ static_cast< css::sdbcx::XKeysSupplier * > ( this ),
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ),
+ static_cast< css::sdbcx::XRename * > ( this ),
+ static_cast< css::sdbcx::XAlterTable * > ( this )
+ );
+ return ret;
+}
+
+OUString Table::getName( )
+{
+ Statics & st = getStatics();
+ return concatQualified(
+ extractStringProperty( this, st.SCHEMA_NAME ),
+ extractStringProperty( this, st.NAME ) );
+}
+
+void Table::setName( const OUString& aName )
+{
+ rename( aName );
+}
+
+
+TableDescriptor::TableDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.tableDescriptor.implName,
+ getStatics().refl.tableDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.tableDescriptor.pProps )
+{
+}
+
+Reference< XNameAccess > TableDescriptor::getColumns( )
+{
+ if( ! m_columns.is() )
+ {
+ m_columns = new ColumnDescriptors(m_xMutex, m_conn, m_pSettings );
+ }
+ return m_columns;
+}
+
+Reference< XNameAccess > TableDescriptor::getIndexes()
+{
+ if( ! m_indexes.is() )
+ {
+ m_indexes = ::pq_sdbc_driver::IndexDescriptors::create(
+ m_xMutex,
+ m_conn,
+ m_pSettings);
+ }
+ return m_indexes;
+}
+
+Reference< XIndexAccess > TableDescriptor::getKeys( )
+{
+ if( ! m_keys.is() )
+ {
+ m_keys = ::pq_sdbc_driver::KeyDescriptors::create(
+ m_xMutex,
+ m_conn,
+ m_pSettings );
+ }
+ return m_keys;
+}
+
+
+Sequence<Type > TableDescriptor::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XIndexesSupplier>::get(),
+ cppu::UnoType<css::sdbcx::XKeysSupplier>::get(),
+ cppu::UnoType<css::sdbcx::XColumnsSupplier>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> TableDescriptor::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any TableDescriptor::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XIndexesSupplier * > ( this ),
+ static_cast< css::sdbcx::XKeysSupplier * > ( this ),
+ static_cast< css::sdbcx::XColumnsSupplier * > ( this ));
+ return ret;
+}
+
+
+Reference< XPropertySet > TableDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<TableDescriptor> pTable = new TableDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+
+ // TODO: deep copies
+ pTable->m_values = m_values;
+
+ return Reference< XPropertySet > ( pTable );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xtable.hxx b/connectivity/source/drivers/postgresql/pq_xtable.hxx
new file mode 100644
index 000000000..7c8ca73f5
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xtable.hxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
+#include <com/sun/star/sdbcx/XKeysSupplier.hpp>
+#include <com/sun/star/sdbcx/XRename.hpp>
+#include <com/sun/star/sdbcx/XAlterTable.hpp>
+
+#include "pq_xbase.hxx"
+#include "pq_xcolumns.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class Columns;
+
+class Table : public ReflectionBase,
+ public css::sdbcx::XColumnsSupplier,
+ public css::sdbcx::XIndexesSupplier,
+ public css::sdbcx::XKeysSupplier,
+ public css::sdbcx::XRename,
+ public css::sdbcx::XAlterTable
+{
+ css::uno::Reference< css::container::XNameAccess > m_columns;
+ css::uno::Reference< css::container::XIndexAccess > m_keys;
+ css::uno::Reference< css::container::XNameAccess > m_indexes;
+ rtl::Reference<Columns> m_pColumns;
+
+public:
+ Table( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+ // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+ // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+ // XIndexesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getIndexes( ) override;
+
+ // XKeysSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL
+ getKeys( ) override;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ // XAlterTable
+ virtual void SAL_CALL alterColumnByName(
+ const OUString& colName,
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+ virtual void SAL_CALL alterColumnByIndex(
+ sal_Int32 index,
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+ // XNamed
+ virtual OUString SAL_CALL getName( ) override;
+ virtual void SAL_CALL setName( const OUString& aName ) override;
+};
+
+
+class TableDescriptor
+ : public ReflectionBase,
+ public css::sdbcx::XColumnsSupplier,
+ public css::sdbcx::XIndexesSupplier,
+ public css::sdbcx::XKeysSupplier
+{
+ css::uno::Reference< css::container::XNameAccess > m_columns;
+ css::uno::Reference< css::container::XIndexAccess > m_keys;
+ css::uno::Reference< css::container::XNameAccess > m_indexes;
+
+public:
+ TableDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+public: // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+public: // XColumnsSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getColumns( ) override;
+
+public: // XIndexesSupplier
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL
+ getIndexes( ) override;
+
+public: // XKeysSupplier
+ virtual css::uno::Reference< css::container::XIndexAccess > SAL_CALL
+ getKeys( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+};
+
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xtables.cxx b/connectivity/source/drivers/postgresql/pq_xtables.cxx
new file mode 100644
index 000000000..423ec81f2
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xtables.cxx
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbcx/Privilege.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xtables.hxx"
+#include "pq_xviews.hxx"
+#include "pq_xtable.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+
+using com::sun::star::container::XEnumerationAccess;
+using com::sun::star::container::XEnumeration;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XResultSet;
+using com::sun::star::sdbc::XDatabaseMetaData;
+using com::sun::star::sdbcx::XColumnsSupplier;
+using com::sun::star::sdbcx::XKeysSupplier;
+
+namespace pq_sdbc_driver
+{
+Tables::Tables(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : Container( refMutex, origin, pSettings, getStatics().TABLE )
+{}
+
+Tables::~Tables()
+{}
+
+void Tables::refresh()
+{
+ try
+ {
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ Reference< XDatabaseMetaData > meta = m_origin->getMetaData();
+
+ Reference< XResultSet > rs =
+ meta->getTables( Any(), st.cPERCENT,st.cPERCENT, Sequence< OUString > () );
+
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ String2IntMap map;
+
+ m_values.clear();
+ sal_Int32 tableIndex = 0;
+ while( rs->next() )
+ {
+ // if creating all these tables turns out to have too bad performance, we might
+ // instead offer a factory interface
+ rtl::Reference<Table> pTable =
+ new Table( m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pTable;
+
+ OUString name = xRow->getString( TABLE_INDEX_NAME+1);
+ OUString schema = xRow->getString( TABLE_INDEX_SCHEMA+1);
+ pTable->setPropertyValue_NoBroadcast_public(
+ st.CATALOG_NAME , Any(xRow->getString( TABLE_INDEX_CATALOG+1) ) );
+ pTable->setPropertyValue_NoBroadcast_public( st.NAME , Any( name ) );
+ pTable->setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME , Any( schema ));
+ pTable->setPropertyValue_NoBroadcast_public(
+ st.TYPE , Any( xRow->getString( TABLE_INDEX_TYPE+1) ) );
+ pTable->setPropertyValue_NoBroadcast_public(
+ st.DESCRIPTION , Any( xRow->getString( TABLE_INDEX_REMARKS+1) ) );
+ pTable->setPropertyValue_NoBroadcast_public(
+ st.PRIVILEGES ,
+ Any( sal_Int32( css::sdbcx::Privilege::SELECT |
+ css::sdbcx::Privilege::INSERT |
+ css::sdbcx::Privilege::UPDATE |
+ css::sdbcx::Privilege::DELETE |
+ css::sdbcx::Privilege::READ |
+ css::sdbcx::Privilege::CREATE |
+ css::sdbcx::Privilege::ALTER |
+ css::sdbcx::Privilege::REFERENCE |
+ css::sdbcx::Privilege::DROP ) ) );
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ schema + "." + name ] = tableIndex;
+ ++tableIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( const css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+static void appendColumnList(
+ OUStringBuffer &buf, const Reference< XColumnsSupplier > & columnSupplier, ConnectionSettings *settings )
+{
+ if( !columnSupplier.is() )
+ return;
+
+ Reference< XEnumerationAccess > columns( columnSupplier->getColumns(),UNO_QUERY );
+ if( !columns.is() )
+ return;
+
+ Reference< XEnumeration > xEnum( columns->createEnumeration() );
+ bool first = true;
+ Statics & st = getStatics();
+
+ while( xEnum.is() && xEnum->hasMoreElements() )
+ {
+ if( first )
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append( ", " );
+ }
+ Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
+ OUString name = extractStringProperty( column, st.NAME );
+ OUString defaultValue = extractStringProperty( column, st.DEFAULT_VALUE );
+ bool isNullable = extractBoolProperty( column, st.IS_NULLABLE );
+ bool isAutoIncrement = extractBoolProperty( column, st.IS_AUTO_INCREMENT );
+
+ bufferQuoteIdentifier( buf, name, settings );
+
+ OUString type = sqltype2string( column );
+ if( isAutoIncrement )
+ {
+ sal_Int32 dataType = 0;
+ column->getPropertyValue( st.TYPE ) >>= dataType;
+ if( css::sdbc::DataType::INTEGER == dataType )
+ {
+ buf.append( " serial ");
+ isNullable = false;
+ }
+ else if( css::sdbc::DataType::BIGINT == dataType )
+ {
+ buf.append( " serial8 " );
+ isNullable = false;
+ }
+ else
+ buf.append( type );
+ }
+ else
+ {
+ buf.append( type );
+ }
+ if( !defaultValue.isEmpty() )
+ {
+ bufferQuoteConstant( buf, defaultValue, settings );
+ }
+
+ if( ! isNullable )
+ buf.append( " NOT NULL " );
+
+ }
+}
+
+static void appendKeyList(
+ OUStringBuffer & buf, const Reference< XKeysSupplier > &keySupplier, ConnectionSettings *settings )
+{
+ if( !keySupplier.is() )
+ return;
+
+ Reference< XEnumerationAccess > keys( keySupplier->getKeys(), UNO_QUERY );
+ if(keys.is() )
+ {
+ Reference< XEnumeration > xEnum = keys->createEnumeration();
+ while( xEnum.is() && xEnum->hasMoreElements() )
+ {
+ buf.append( ", " );
+ Reference< XPropertySet > key( xEnum->nextElement(), UNO_QUERY );
+ bufferKey2TableConstraint( buf, key, settings );
+ }
+ }
+}
+
+void Tables::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Reference< XStatement > stmt =
+ m_origin->createStatement();
+
+ Statics &st = getStatics();
+ OUString name,schema;
+ descriptor->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
+ descriptor->getPropertyValue( st.NAME ) >>= name;
+
+ TransactionGuard transaction( stmt );
+
+ OUStringBuffer buf( 128 );
+ buf.append( "CREATE TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schema, name , m_pSettings);
+ buf.append( "(" );
+
+ // columns
+ Reference< XColumnsSupplier > supplier( descriptor, UNO_QUERY );
+ appendColumnList( buf, supplier, m_pSettings );
+
+ appendKeyList( buf, Reference< XKeysSupplier >( descriptor, UNO_QUERY ), m_pSettings );
+
+ buf.append( ") " );
+ // execute the creation !
+ transaction.executeUpdate( buf.makeStringAndClear() );
+
+ // description...
+ OUString description = extractStringProperty( descriptor, st.DESCRIPTION );
+ if( !description.isEmpty() )
+ {
+ buf.truncate();
+ buf.append( "COMMENT ON TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schema, name, m_pSettings );
+ buf.append( "IS " );
+ bufferQuoteConstant( buf, description, m_pSettings);
+
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+
+ // column descriptions
+ if( supplier.is() )
+ {
+ Reference< XEnumerationAccess > columns( supplier->getColumns(),UNO_QUERY );
+ if( columns.is() )
+ {
+ Reference< XEnumeration > xEnum( columns->createEnumeration() );
+ while( xEnum.is() && xEnum->hasMoreElements() )
+ {
+ Reference< XPropertySet > column( xEnum->nextElement(), UNO_QUERY );
+ description = extractStringProperty( column,st.DESCRIPTION );
+ if( !description.isEmpty() )
+ {
+ buf.truncate();
+ buf.append( "COMMENT ON COLUMN " );
+ bufferQuoteQualifiedIdentifier(
+ buf, schema, name, extractStringProperty( column, st.NAME ), m_pSettings );
+ buf.append( "IS " );
+ bufferQuoteConstant( buf, description, m_pSettings );
+ transaction.executeUpdate( buf.makeStringAndClear() );
+ }
+ }
+ }
+ }
+
+ transaction.commit();
+
+ disposeNoThrow( stmt );
+ // TODO: cheaper recalculate
+// Container::append( concatQualified( schema, name ), descriptor ); // maintain the lists
+ refresh();
+}
+
+void Tables::dropByIndex( sal_Int32 index )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "TABLES: Index out of range (allowed 0 to " + OUString::number(m_values.size() -1)
+ + ", got " + OUString::number( index ) + ")",
+ *this );
+ }
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+ Statics &st = getStatics();
+ OUString name,schema;
+ set->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
+ set->getPropertyValue( st.NAME ) >>= name;
+ if( extractStringProperty( set, st.TYPE ) == st.VIEW && m_pSettings->views.is() )
+ {
+ m_pSettings->pViewsImpl->dropByName( concatQualified( schema, name ) );
+ }
+ else
+ {
+ OUStringBuffer update( 128 );
+ update.append( "DROP " );
+ if( extractStringProperty( set, st.TYPE ) == st.VIEW )
+ update.append( "VIEW " );
+ else
+ update.append( "TABLE " );
+ bufferQuoteQualifiedIdentifier( update, schema, name, m_pSettings );
+ Reference< XStatement > stmt = m_origin->createStatement( );
+ DisposeGuard dispGuard( stmt );
+ stmt->executeUpdate( update.makeStringAndClear() );
+ }
+
+ Container::dropByIndex( index );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Tables::createDataDescriptor()
+{
+ return new TableDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > Tables::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ rtl::Reference<Tables> *ppTables)
+{
+ *ppTables = new Tables( refMutex, origin, pSettings );
+ (*ppTables)->refresh();
+
+ return *ppTables;
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xtables.hxx b/connectivity/source/drivers/postgresql/pq_xtables.hxx
new file mode 100644
index 000000000..9222db82c
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xtables.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+struct ConnectionSettings;
+
+class Tables : public Container
+{
+
+public: // instances Tables 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ rtl::Reference<Tables> * ppTables);
+
+protected:
+ Tables(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+ virtual ~Tables() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+// virtual void SAL_CALL dropByName( const OUString& elementName )
+// throw (css::sdbc::SQLException,
+// css::container::NoSuchElementException,
+// css::uno::RuntimeException);
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+protected:
+ using Container::disposing;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xuser.cxx b/connectivity/source/drivers/postgresql/pq_xuser.cxx
new file mode 100644
index 000000000..4d0a01f63
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xuser.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include "pq_xuser.hxx"
+#include "pq_tools.hxx"
+#include "pq_statics.hxx"
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+User::User( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.user.implName,
+ getStatics().refl.user.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.user.pProps )
+{}
+
+Reference< XPropertySet > User::createDataDescriptor( )
+{
+ rtl::Reference<UserDescriptor> pUser = new UserDescriptor( m_xMutex, m_conn, m_pSettings );
+ pUser->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pUser );
+}
+
+
+Sequence<Type > User::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XUser>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> User::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any User::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XUser * > ( this ) );
+ return ret;
+}
+
+
+void User::changePassword(
+ const OUString&, const OUString& newPassword )
+{
+ OUStringBuffer buf(128);
+ buf.append( "ALTER USER " );
+ bufferQuoteIdentifier( buf, extractStringProperty( this, getStatics().NAME ), m_pSettings );
+ buf.append( " PASSWORD " );
+ bufferQuoteConstant( buf, newPassword, m_pSettings );
+ Reference< XStatement > stmt = m_conn->createStatement();
+ DisposeGuard guard( stmt );
+ stmt->executeUpdate( buf.makeStringAndClear() );
+}
+
+sal_Int32 User::getPrivileges( const OUString& objName, sal_Int32 objType )
+{
+ SAL_INFO("connectivity.postgresql", "User::getPrivileges[\"Name\"] got called for " << objName << "(type=" << objType << ")");
+ // all privileges
+ return 0xffffffff;
+}
+
+sal_Int32 User::getGrantablePrivileges( const OUString&, sal_Int32 )
+{
+ // all privileges
+ return 0xffffffff;
+}
+
+void User::grantPrivileges( const OUString&, sal_Int32, sal_Int32 )
+{
+ throw css::sdbc::SQLException("pq_driver: privilege change not implemented yet",
+ *this, OUString(), 1, Any() );
+}
+
+void User::revokePrivileges( const OUString&, sal_Int32, sal_Int32 )
+{
+ throw css::sdbc::SQLException("pq_driver: privilege change not implemented yet",
+ *this, OUString(), 1, Any() );
+}
+
+
+UserDescriptor::UserDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings )
+ : ReflectionBase(
+ getStatics().refl.userDescriptor.implName,
+ getStatics().refl.userDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.userDescriptor.pProps )
+{}
+
+Reference< XPropertySet > UserDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<UserDescriptor> pUser = new UserDescriptor( m_xMutex, m_conn, m_pSettings );
+ pUser->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pUser );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xuser.hxx b/connectivity/source/drivers/postgresql/pq_xuser.hxx
new file mode 100644
index 000000000..702787a67
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xuser.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <com/sun/star/sdbcx/XUser.hpp>
+
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class User : public ReflectionBase,
+ public css::sdbcx::XUser
+{
+
+public:
+ User( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+ // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+ // XUser : XAuthorizable
+ virtual sal_Int32 SAL_CALL getPrivileges( const OUString& objName, sal_Int32 objType ) override;
+ virtual sal_Int32 SAL_CALL getGrantablePrivileges( const OUString& objName, sal_Int32 objType ) override;
+ virtual void SAL_CALL grantPrivileges( const OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) override;
+ virtual void SAL_CALL revokePrivileges( const OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) override;
+ virtual void SAL_CALL changePassword( const OUString& oldPassword, const OUString& newPassword ) override;
+};
+
+class UserDescriptor : public ReflectionBase
+{
+public:
+ UserDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+};
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xusers.cxx b/connectivity/source/drivers/postgresql/pq_xusers.cxx
new file mode 100644
index 000000000..08cdf2d1c
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xusers.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xusers.hxx"
+#include "pq_xuser.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+
+using com::sun::star::container::NoSuchElementException;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XResultSet;
+
+namespace pq_sdbc_driver
+{
+Users::Users(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : Container( refMutex, origin, pSettings, getStatics().USER )
+{}
+
+Users::~Users()
+{}
+
+void Users::refresh()
+{
+ try
+ {
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ Reference< XStatement > stmt = m_origin->createStatement();
+
+ Reference< XResultSet > rs = stmt->executeQuery( "SELECT usename FROM pg_shadow" );
+
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ String2IntMap map;
+
+ m_values.clear();
+ sal_Int32 tableIndex = 0;
+ while( rs->next() )
+ {
+ rtl::Reference<User> pUser =
+ new User( m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pUser;
+
+ OUString name = xRow->getString( 1);
+ pUser->setPropertyValue_NoBroadcast_public(
+ st.NAME , Any(xRow->getString( TABLE_INDEX_CATALOG+1) ) );
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ name ] = tableIndex;
+ ++tableIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void Users::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ OUStringBuffer update( 128 );
+ update.append( "CREATE USER " );
+ bufferQuoteIdentifier( update, extractStringProperty( descriptor, getStatics().NAME ), m_pSettings );
+ update.append( " PASSWORD " );
+ bufferQuoteConstant( update, extractStringProperty( descriptor, getStatics().PASSWORD ), m_pSettings );
+
+ Reference< XStatement > stmt = m_origin->createStatement( );
+ DisposeGuard disposeGuard( stmt );
+ stmt->executeUpdate( update.makeStringAndClear() );
+}
+
+void Users::dropByName( const OUString& elementName )
+{
+ String2IntMap::const_iterator ii = m_name2index.find( elementName );
+ if( ii == m_name2index.end() )
+ {
+ throw css::container::NoSuchElementException(
+ "User " + elementName + " is unknown, so it can't be dropped",
+ *this );
+ }
+ dropByIndex( ii->second );
+}
+
+void Users::dropByIndex( sal_Int32 index )
+{
+
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "USERS: Index out of range (allowed 0 to "
+ + OUString::number( m_values.size() -1 )
+ + ", got " + OUString::number( index )
+ + ")",
+ *this );
+ }
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+ OUString name;
+ set->getPropertyValue( getStatics().NAME ) >>= name;
+
+ OUStringBuffer update( 128 );
+ update.append( "DROP USER " );
+ bufferQuoteIdentifier( update, name, m_pSettings );
+
+ Reference< XStatement > stmt = m_origin->createStatement( );
+ DisposeGuard disposeGuard( stmt );
+ stmt->executeUpdate( update.makeStringAndClear() );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Users::createDataDescriptor()
+{
+ return new UserDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > Users::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+{
+ rtl::Reference<Users> pUsers = new Users( refMutex, origin, pSettings );
+ pUsers->refresh();
+
+ return pUsers;
+}
+
+void Users::disposing()
+{
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xusers.hxx b/connectivity/source/drivers/postgresql/pq_xusers.hxx
new file mode 100644
index 000000000..f95ec1749
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xusers.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+class Users final : public Container
+{
+
+public: // instances Tables 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+private:
+ Users(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings );
+
+ virtual ~Users() override;
+
+public:
+ // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+ // XDrop
+ virtual void SAL_CALL dropByName( const OUString& elementName ) override;
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+ // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+private:
+ virtual void SAL_CALL disposing() override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xview.cxx b/connectivity/source/drivers/postgresql/pq_xview.cxx
new file mode 100644
index 000000000..2b8f61be7
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xview.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include "pq_xview.hxx"
+#include "pq_xviews.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::SQLException;
+
+namespace pq_sdbc_driver
+{
+
+View::View( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.view.implName,
+ getStatics().refl.view.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.view.pProps )
+{}
+
+Reference< XPropertySet > View::createDataDescriptor( )
+{
+ rtl::Reference<ViewDescriptor> pView = new ViewDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pView->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pView );
+}
+
+void View::rename( const OUString& newName )
+{
+ MutexGuard guard( m_xMutex->GetMutex() );
+
+ Statics & st = getStatics();
+
+ OUString oldName = extractStringProperty(this,st.NAME );
+ OUString schema = extractStringProperty(this,st.SCHEMA_NAME );
+ OUString fullOldName = concatQualified( schema, oldName );
+
+ OUString newTableName;
+ OUString newSchemaName;
+ // OOo2.0 passes schema + dot + new-table-name while
+ // OO1.1.x passes new Name without schema
+ // in case name contains a dot, it is interpreted as schema.tablename
+ if( newName.indexOf( '.' ) >= 0 )
+ {
+ splitConcatenatedIdentifier( newName, &newSchemaName, &newTableName );
+ }
+ else
+ {
+ newTableName = newName;
+ newSchemaName = schema;
+ }
+ OUString fullNewName = concatQualified( newSchemaName, newTableName );
+
+ if( schema != newSchemaName )
+ {
+ try
+ {
+ OUStringBuffer buf(128);
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier(buf, schema, oldName, m_pSettings );
+ buf.append( "SET SCHEMA" );
+ bufferQuoteIdentifier( buf, newSchemaName, m_pSettings );
+ Reference< XStatement > statement = m_conn->createStatement();
+ statement->executeUpdate( buf.makeStringAndClear() );
+ setPropertyValue_NoBroadcast_public( st.SCHEMA_NAME, Any(newSchemaName) );
+ disposeNoThrow( statement );
+ schema = newSchemaName;
+ }
+ catch( css::sdbc::SQLException &e )
+ {
+ OUString buf( e.Message + "(NOTE: Only postgresql server >= V8.1 support changing a table's schema)" );
+ e.Message = buf;
+ throw;
+ }
+
+ }
+ if( oldName != newTableName )
+ {
+ OUStringBuffer buf(128);
+ buf.append( "ALTER TABLE" );
+ bufferQuoteQualifiedIdentifier( buf, schema, oldName, m_pSettings );
+ buf.append( "RENAME TO" );
+ bufferQuoteIdentifier( buf, newTableName, m_pSettings );
+ Reference< XStatement > statement = m_conn->createStatement();
+ statement->executeUpdate( buf.makeStringAndClear() );
+ setPropertyValue_NoBroadcast_public( st.NAME, Any(newTableName) );
+ }
+
+ // inform the container of the name change !
+ if( m_pSettings->views.is() )
+ {
+ m_pSettings->pViewsImpl->rename( fullOldName, fullNewName );
+ }
+}
+
+Sequence<Type > View::getTypes()
+{
+ static cppu::OTypeCollection collection(
+ cppu::UnoType<css::sdbcx::XRename>::get(),
+ ReflectionBase::getTypes());
+
+ return collection.getTypes();
+}
+
+Sequence< sal_Int8> View::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+Any View::queryInterface( const Type & reqType )
+{
+ Any ret = ReflectionBase::queryInterface( reqType );
+ if( ! ret.hasValue() )
+ ret = ::cppu::queryInterface(
+ reqType,
+ static_cast< css::sdbcx::XRename * > ( this )
+ );
+ return ret;
+}
+
+OUString View::getName( )
+{
+ Statics & st = getStatics();
+ return concatQualified(
+ extractStringProperty( this, st.SCHEMA_NAME ),
+ extractStringProperty( this, st.NAME ) );
+}
+
+void View::setName( const OUString& aName )
+{
+ rename( aName );
+}
+
+
+ViewDescriptor::ViewDescriptor(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings)
+ : ReflectionBase(
+ getStatics().refl.viewDescriptor.implName,
+ getStatics().refl.viewDescriptor.serviceNames,
+ refMutex,
+ connection,
+ pSettings,
+ * getStatics().refl.viewDescriptor.pProps )
+{}
+
+Reference< XPropertySet > ViewDescriptor::createDataDescriptor( )
+{
+ rtl::Reference<ViewDescriptor> pView = new ViewDescriptor(
+ m_xMutex, m_conn, m_pSettings );
+ pView->copyValuesFrom( this );
+
+ return Reference< XPropertySet > ( pView );
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xview.hxx b/connectivity/source/drivers/postgresql/pq_xview.hxx
new file mode 100644
index 000000000..f68b5535a
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xview.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <com/sun/star/sdbcx/XRename.hpp>
+
+#include "pq_xbase.hxx"
+
+namespace pq_sdbc_driver
+{
+class View : public ReflectionBase,
+ public css::sdbcx::XRename
+{
+public:
+ View( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override { ReflectionBase::acquire(); }
+ virtual void SAL_CALL release() noexcept override { ReflectionBase::release(); }
+ virtual css::uno::Any SAL_CALL queryInterface(
+ const css::uno::Type & reqType ) override;
+
+ // XTypeProvider, first implemented by OPropertySetHelper
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ virtual css::uno::Sequence< sal_Int8> SAL_CALL getImplementationId() override;
+
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+
+ // XRename
+ virtual void SAL_CALL rename( const OUString& newName ) override;
+
+ // XNamed
+ virtual OUString SAL_CALL getName( ) override;
+ virtual void SAL_CALL setName( const OUString& aName ) override;
+
+};
+
+
+class ViewDescriptor : public ReflectionBase
+{
+public:
+ ViewDescriptor( const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & connection,
+ ConnectionSettings *pSettings);
+
+ // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL
+ createDataDescriptor( ) override;
+};
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xviews.cxx b/connectivity/source/drivers/postgresql/pq_xviews.cxx
new file mode 100644
index 000000000..1f5b6c4fa
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xviews.cxx
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <o3tl/safeint.hxx>
+
+#include "pq_xviews.hxx"
+#include "pq_xview.hxx"
+#include "pq_xtables.hxx"
+#include "pq_statics.hxx"
+#include "pq_tools.hxx"
+
+using osl::MutexGuard;
+
+using com::sun::star::beans::XPropertySet;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::Reference;
+
+using com::sun::star::container::NoSuchElementException;
+
+using com::sun::star::sdbc::XRow;
+using com::sun::star::sdbc::XStatement;
+using com::sun::star::sdbc::XResultSet;
+
+
+namespace pq_sdbc_driver
+{
+Views::Views(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings )
+ : Container( refMutex, origin, pSettings, getStatics().VIEW )
+{}
+
+Views::~Views()
+{}
+
+void Views::refresh()
+{
+ try
+ {
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ Statics & st = getStatics();
+
+ Reference< XStatement > stmt = m_origin->createStatement();
+
+ Reference< XResultSet > rs = stmt->executeQuery("SELECT "
+ "DISTINCT ON( pg_namespace.nspname, relname) " // needed because of duplicates
+ "pg_namespace.nspname," // 1
+ "relname," // 2
+ "pg_get_viewdef(ev_class) " // 3
+ "FROM pg_namespace, pg_class, pg_rewrite "
+ "WHERE pg_namespace.oid = relnamespace "
+ "AND pg_class.oid = ev_class "
+ "AND relkind=\'v\'" );
+
+ Reference< XRow > xRow( rs , UNO_QUERY );
+
+ m_values.clear();
+ String2IntMap map;
+ sal_Int32 viewIndex = 0;
+
+ while( rs->next() )
+ {
+ OUString table, schema, command;
+ schema = xRow->getString( 1 );
+ table = xRow->getString( 2 );
+ command = xRow->getString( 3 );
+
+ rtl::Reference<View> pView = new View (m_xMutex, m_origin, m_pSettings );
+ Reference< css::beans::XPropertySet > prop = pView;
+
+ pView->setPropertyValue_NoBroadcast_public(st.NAME , Any(table) );
+ pView->setPropertyValue_NoBroadcast_public(st.SCHEMA_NAME, Any(schema) );
+ pView->setPropertyValue_NoBroadcast_public(st.COMMAND, Any(command) );
+
+ {
+ m_values.push_back( Any( prop ) );
+ map[ schema + "." + table ] = viewIndex;
+ ++viewIndex;
+ }
+ }
+ m_name2index.swap( map );
+ }
+ catch ( css::sdbc::SQLException & e )
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException( e.Message,
+ e.Context, anyEx );
+ }
+ fire( RefreshedBroadcaster( *this ) );
+}
+
+
+void Views::appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+
+ Statics &st = getStatics();
+ OUString name,schema,command;
+ descriptor->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
+ descriptor->getPropertyValue( st.NAME ) >>= name;
+ descriptor->getPropertyValue( st.COMMAND ) >>= command;
+
+ Reference< XStatement > stmt = m_origin->createStatement();
+
+ OUStringBuffer buf( 128 );
+
+ buf.append( "CREATE VIEW ");
+ bufferQuoteQualifiedIdentifier( buf, schema, name, m_pSettings );
+ buf.append(" AS " + command );
+
+ stmt->executeUpdate( buf.makeStringAndClear() );
+
+ disposeNoThrow( stmt );
+ refresh();
+ if( m_pSettings->tables.is() )
+ {
+ m_pSettings->pTablesImpl->refresh();
+ }
+}
+
+void Views::dropByName( const OUString& elementName )
+{
+ String2IntMap::const_iterator ii = m_name2index.find( elementName );
+ if( ii == m_name2index.end() )
+ {
+ throw css::container::NoSuchElementException(
+ "View " + elementName + " is unknown, so it can't be dropped", *this );
+ }
+ dropByIndex( ii->second );
+}
+
+void Views::dropByIndex( sal_Int32 index )
+{
+ osl::MutexGuard guard( m_xMutex->GetMutex() );
+ if( index < 0 || o3tl::make_unsigned(index) >= m_values.size() )
+ {
+ throw css::lang::IndexOutOfBoundsException(
+ "VIEWS: Index out of range (allowed 0 to " + OUString::number(m_values.size() -1)
+ + ", got " + OUString::number( index ) + ")",
+ *this );
+ }
+
+ Reference< XPropertySet > set;
+ m_values[index] >>= set;
+ Statics &st = getStatics();
+ OUString name,schema;
+ set->getPropertyValue( st.SCHEMA_NAME ) >>= schema;
+ set->getPropertyValue( st.NAME ) >>= name;
+
+ Reference< XStatement > stmt = m_origin->createStatement( );
+
+ stmt->executeUpdate( "DROP VIEW \"" + schema + "\".\"" + name + "\"" );
+}
+
+
+css::uno::Reference< css::beans::XPropertySet > Views::createDataDescriptor()
+{
+ return new ViewDescriptor( m_xMutex, m_origin, m_pSettings );
+}
+
+Reference< css::container::XNameAccess > Views::create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ rtl::Reference<Views> *ppViews)
+{
+ *ppViews = new Views( refMutex, origin, pSettings );
+ (*ppViews)->refresh();
+
+ return *ppViews;
+}
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/postgresql/pq_xviews.hxx b/connectivity/source/drivers/postgresql/pq_xviews.hxx
new file mode 100644
index 000000000..04137b686
--- /dev/null
+++ b/connectivity/source/drivers/postgresql/pq_xviews.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * Effective License of whole file:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
+ *
+ * The Contents of this file are made available subject to the terms of
+ * the GNU Lesser General Public License Version 2.1
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * Contributor(s): Joerg Budischewski
+ *
+ * All parts contributed on or after August 2011:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <rtl/ref.hxx>
+
+#include "pq_xcontainer.hxx"
+
+namespace pq_sdbc_driver
+{
+
+struct ConnectionSettings;
+
+class Views : public Container
+{
+
+public: // instances Views 'exception safe'
+ static css::uno::Reference< css::container::XNameAccess > create(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings,
+ rtl::Reference<Views> *ppViews );
+
+protected:
+ Views(
+ const ::rtl::Reference< comphelper::RefCountedMutex > & refMutex,
+ const css::uno::Reference< css::sdbc::XConnection > & origin,
+ ConnectionSettings *pSettings);
+
+ virtual ~Views() override;
+
+public: // XAppend
+ virtual void SAL_CALL appendByDescriptor(
+ const css::uno::Reference< css::beans::XPropertySet >& descriptor ) override;
+
+public: // XDrop
+ virtual void SAL_CALL dropByName( const OUString& elementName ) override;
+ virtual void SAL_CALL dropByIndex( sal_Int32 index ) override;
+
+public: // XRefreshable
+ virtual void SAL_CALL refresh( ) override;
+
+public: // XDataDescriptorFactory
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL createDataDescriptor( ) override;
+
+protected:
+ using Container::disposing;
+
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */