Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexContainer.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexContainer.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexContainer.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexContainer.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,208 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdbc.IndexType;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbc.XDatabaseMetaData;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import 
com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxIndexDescriptor;
+import com.sun.star.sdbcx.comp.postgresql.util.ComposeRule;
+import com.sun.star.sdbcx.comp.postgresql.util.DbTools;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.sdbcx.comp.postgresql.util.StandardSQLState;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.UnoRuntime;
+
+public class OIndexContainer extends OContainer {
+    protected OTable table;
+    
+    public OIndexContainer(Object lock, List<String> names, boolean 
isCaseSensitive, OTable table) {
+        super(lock, isCaseSensitive, names);
+        this.table = table;
+    }
+    
+    @Override
+    public XPropertySet createDescriptor() {
+        return SdbcxIndexDescriptor.create(isCaseSensitive());
+    }
+
+    @Override
+    public XPropertySet createObject(String name) throws SQLException {
+        try {
+            XConnection connection = table.getConnection();
+            if (connection == null) {
+                return null;
+            }
+            
+            XPropertySet ret = null;
+            String qualifier = "";
+            String subname;
+            int len = name.indexOf('.');
+            if (len >= 0) {
+                qualifier = name.substring(0, len);
+                subname = name.substring(len + 1);
+            } else {
+                subname = name;
+            }
+            
+            Object catalog = 
table.getPropertyValue(PropertyIds.CATALOGNAME.name);
+            String schemaName = 
AnyConverter.toString(table.getPropertyValue(PropertyIds.SCHEMANAME.name));
+            String tableName = 
AnyConverter.toString(table.getPropertyValue(PropertyIds.NAME.name));
+            XResultSet results = null;
+            try {
+                results = connection.getMetaData().getIndexInfo(catalog, 
schemaName, tableName, false, false);
+                if (results != null) {
+                    XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                    boolean found = false;
+                    boolean isUnique = false;
+                    int clustered = -1;
+                    boolean isPrimaryKeyIndex = false;
+                    ArrayList<String> columnNames = new ArrayList<>();
+                    while (results.next()) {
+                        isUnique  = !row.getBoolean(4);
+                        if ((qualifier.isEmpty() || 
row.getString(5).equals(qualifier)) && row.getString(6).equals(subname)) {
+                            found = true;
+                            clustered = row.getShort(7);
+                            isPrimaryKeyIndex = 
isPrimaryKeyIndex(connection.getMetaData(), catalog, schemaName, tableName, 
subname);
+                            String columnName = row.getString(9);
+                            if (!row.wasNull()) {
+                                columnNames.add(columnName);
+                            }
+                        }
+                    }
+                    if (found) {
+                        ret = OIndex.create(subname, isCaseSensitive(), 
qualifier, isUnique, isPrimaryKeyIndex, clustered == IndexType.CLUSTERED,
+                                columnNames, table);
+                    }
+                }
+            } finally {
+                CompHelper.disposeComponent(results);
+            }
+            return ret;
+        } catch (WrappedTargetException | UnknownPropertyException | 
IllegalArgumentException exception) {
+            throw new SQLException("Error", this, 
StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception);
+        }
+    }
+    
+    private static boolean isPrimaryKeyIndex(XDatabaseMetaData metadata, 
Object catalog, String schema, String table, String name) throws SQLException {
+        XResultSet results = null;
+        try {
+            results = metadata.getPrimaryKeys(catalog, schema, table);
+            if (results != null) {
+                XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                if (results.next()) { // there can be only one primary key
+                    return row.getString(6).equals(name);
+                }
+            }
+            return false;
+        } finally {
+            CompHelper.disposeComponent(results);
+        }
+    }
+    
+    @Override
+    public XPropertySet appendObject(String _rForName, XPropertySet 
descriptor) throws SQLException {
+        try {
+            XConnection connection = table.getConnection();
+            if (connection == null) {
+                return null;
+            }
+            String quote = connection.getMetaData().getIdentifierQuoteString();
+            boolean isUnique = 
AnyConverter.toBoolean(descriptor.getPropertyValue(PropertyIds.ISUNIQUE.name));
+            String composedName = 
DbTools.composeTableName(connection.getMetaData(), table, 
ComposeRule.InIndexDefinitions, false, false, true);
+            StringBuilder columnsText = new StringBuilder();
+            String separator = "";
+            XColumnsSupplier columnsSupplier = 
UnoRuntime.queryInterface(XColumnsSupplier.class, descriptor);
+            XIndexAccess columns = 
UnoRuntime.queryInterface(XIndexAccess.class, columnsSupplier.getColumns());
+            for (int i = 0; i < columns.getCount(); i++) {
+                columnsText.append(separator);
+                separator = ", ";
+                XPropertySet column = 
AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i));
+                columnsText.append(DbTools.quoteName(quote, 
AnyConverter.toString(column.getPropertyValue(PropertyIds.NAME.name))));
+                // FIXME: ::dbtools::getBooleanDataSourceSetting( 
m_pTable->getConnection(), "AddIndexAppendix" );
+                boolean isAscending = 
AnyConverter.toBoolean(column.getPropertyValue(PropertyIds.ISASCENDING.name));
+                columnsText.append(isAscending ? " ASC" : " DESC");
+            }
+            String sql = String.format("CREATE %s INDEX %s ON %s (%s)",
+                    isUnique ? "UNIQUE" : "",
+                    _rForName.isEmpty() ? "" : DbTools.quoteName(quote, 
_rForName),
+                    composedName,
+                    columnsText.toString());
+            XStatement statement = null;
+            try {
+                statement = connection.createStatement();
+                statement.execute(sql);
+            } finally {
+                CompHelper.disposeComponent(statement);
+            }
+            return createObject(_rForName);
+        } catch (WrappedTargetException | UnknownPropertyException | 
IllegalArgumentException | IndexOutOfBoundsException exception) {
+            throw new SQLException("Error", this, 
StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception);
+        }
+    }
+    
+    @Override
+    public void dropObject(int index, String elementName) throws SQLException {
+        XConnection connection = table.getConnection();
+        if (connection == null) {
+            return;
+        }
+        String name;
+        String schema = "";
+        int len = elementName.indexOf('.');
+        if (len >= 0) {
+            schema = elementName.substring(0, len);
+        }
+        name = elementName.substring(len + 1);
+        
+        String composedName = 
DbTools.composeTableName(connection.getMetaData(), table, 
ComposeRule.InTableDefinitions, false, false, true);
+        String indexName = DbTools.composeTableName(connection.getMetaData(), 
"", schema, name, true, ComposeRule.InIndexDefinitions);
+        String sql = String.format("DROP INDEX %s ON %s", indexName, 
composedName);
+        XStatement statement = null;
+        try {
+            statement = connection.createStatement();
+            statement.execute(sql);
+        } finally {
+            CompHelper.disposeComponent(statement);
+        }
+    }
+    
+    @Override
+    public void impl_refresh() {
+        // FIXME
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OIndexContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKey.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKey.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKey.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKey.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,150 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.List;
+
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.lang.DisposedException;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDataDescriptorFactory;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import 
com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter;
+import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxKeyDescriptor;
+import com.sun.star.sdbcx.comp.postgresql.util.DbTools;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.uno.Type;
+
+public class OKey extends ODescriptor
+        implements XDataDescriptorFactory, XColumnsSupplier {
+    
+    protected OTable table;
+    protected String referencedTable;
+    protected int type;
+    protected int updateRule;
+    protected int deleteRule;
+    
+    private OContainer columns;
+
+    protected OKey(Object lock, boolean isCaseSensitive) {
+        super(lock, "", isCaseSensitive);
+        registerProperties();
+    }
+    
+    protected OKey(Object lock, String name, boolean isCaseSensitive, String 
referencedTable, int type,
+            int updateRule, int deleteRule, List<String> columnNames, OTable 
table) {
+        super(lock, name, isCaseSensitive);
+        this.referencedTable = referencedTable;
+        this.type = type;
+        this.updateRule = updateRule;
+        this.deleteRule = deleteRule;
+        this.table = table;
+        registerProperties();
+        columns = new OKeyColumnContainer(lock, this, columnNames);
+    }
+    
+    public static OKey create(String name, boolean isCaseSensitive, String 
referencedTable, int type,
+            int updateRule, int deleteRule, List<String> columnNames, OTable 
table) {
+        final Object lock = new Object();
+        return new OKey(lock, name, isCaseSensitive, referencedTable, type, 
updateRule, deleteRule, columnNames, table);
+    }
+    
+    private void registerProperties() {
+        registerProperty(PropertyIds.REFERENCEDTABLE.name, 
PropertyIds.REFERENCEDTABLE.id, Type.STRING, (short)PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return referencedTable;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.TYPE.name, PropertyIds.TYPE.id, 
Type.LONG, (short)PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return type;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.UPDATERULE.name, 
PropertyIds.UPDATERULE.id, Type.LONG, (short)PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return updateRule;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.DELETERULE.name, 
PropertyIds.DELETERULE.id, Type.LONG, (short)PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return deleteRule;
+                        
+                    }
+                }, null);
+    }
+
+    // XComponent
+    
+    private void checkDisposed() {
+        if (bDisposed) {
+            throw new DisposedException();
+        }
+    }
+
+    // XColumnsSupplier
+    
+    @Override
+    public XNameAccess getColumns() {
+        synchronized (lock) {
+            checkDisposed();
+            return columns;
+        }
+    }
+    
+    // XDataDescriptionFactory
+    
+    public XPropertySet createDataDescriptor() {
+        SdbcxKeyDescriptor descriptor = 
SdbcxKeyDescriptor.create(isCaseSensitive());
+        CompHelper.copyProperties(this, descriptor);
+        try {
+            DbTools.cloneDescriptorColumns(this, descriptor);
+        } catch (SQLException sqlException) {
+        }
+        return descriptor;
+    }
+    
+    public OTable getTable() {
+        return table;
+    }
+
+    @Override
+    public String toString() {
+        return "OKey [referencedTable=" + referencedTable + ", type=" + type + 
", updateRule=" + updateRule + ", deleteRule=" + deleteRule
+                + ", name=" + getName() + "]";
+    }
+    
+    
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKey.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumn.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumn.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumn.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumn.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,101 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import 
com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter;
+import 
com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxKeyColumnDescriptor;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.uno.Type;
+
+public class OKeyColumn extends OColumn {
+    protected String referencedColumn;
+    
+    protected OKeyColumn(Object lock, boolean isCaseSensitive) {
+        super(lock, isCaseSensitive);
+        registerProperties();
+    }
+    
+    protected OKeyColumn(
+            final Object lock,
+            final String referencedColumn,
+            final String name,
+            final String typeName,
+            final String defaultValue,
+            final String description,
+            final int isNullable,
+            final int precision,
+            final int scale,
+            final int type,
+            final boolean isAutoIncrement,
+            final boolean isRowVersion,
+            final boolean isCurrency,
+            final boolean isCaseSensitive) {
+        super(lock, name, typeName, defaultValue, description, isNullable,
+                precision, scale, type, isAutoIncrement, isRowVersion, 
isCurrency, isCaseSensitive);
+        this.referencedColumn = referencedColumn;
+        registerProperties();
+    }
+    
+    public static OKeyColumn create(
+            final String referencedColumn,
+            final String name,
+            final String typeName,
+            final String defaultValue,
+            final int isNullable,
+            final int precision,
+            final int scale,
+            final int type,
+            final boolean isAutoIncrement,
+            final boolean isRowVersion,
+            final boolean isCurrency,
+            final boolean isCaseSensitive) {
+        final Object lock = new Object();
+        return new OKeyColumn(lock, referencedColumn, name, typeName,
+                defaultValue, "", isNullable, precision, scale,
+                type, isAutoIncrement, isRowVersion, isCurrency, 
isCaseSensitive);
+    }
+    
+    private void registerProperties() {
+        registerProperty(PropertyIds.RELATEDCOLUMN.name, 
PropertyIds.RELATEDCOLUMN.id, Type.STRING, PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return referencedColumn;
+                        
+                    }
+                }, null);
+    }
+    
+    // XDataDescriptorFactory
+    
+    @Override
+    public XPropertySet createDataDescriptor() {
+        SdbcxKeyColumnDescriptor descriptor = 
SdbcxKeyColumnDescriptor.create(isCaseSensitive());
+        synchronized (lock) {
+            CompHelper.copyProperties(this, descriptor);
+        }
+        return descriptor;
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumn.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumnContainer.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumnContainer.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumnContainer.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumnContainer.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,115 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.List;
+
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XRow;
+import 
com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxKeyColumnDescriptor;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.sdbcx.comp.postgresql.util.StandardSQLState;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.UnoRuntime;
+
+public class OKeyColumnContainer extends OContainer {
+    private OKey key;
+    
+    public OKeyColumnContainer(Object lock, OKey key, List<String> 
columnNames) {
+        super(lock, true, columnNames);
+        this.key = key;
+    }
+    
+    @Override
+    public XPropertySet createDescriptor() {
+        return SdbcxKeyColumnDescriptor.create(isCaseSensitive());
+    }
+    
+    @Override
+    public XPropertySet createObject(String name) throws SQLException {
+        try {
+            XPropertySet tableProperties = 
UnoRuntime.queryInterface(XPropertySet.class, key.getTable());
+            Object catalog = 
tableProperties.getPropertyValue(PropertyIds.CATALOGNAME.name);
+            String schema = 
AnyConverter.toString(tableProperties.getPropertyValue(PropertyIds.SCHEMANAME.name));
+            String table = 
AnyConverter.toString(tableProperties.getPropertyValue(PropertyIds.NAME.name));
+            
+            XResultSet results = 
key.getTable().getConnection().getMetaData().getImportedKeys(catalog, schema, 
table);
+            String refColumnName = "";
+            if (results != null) {
+                XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                while (results.next()) {
+                    if (row.getString(8).equals(name) && 
key.getName().equals(row.getString(12))) {
+                        refColumnName = row.getString(4);
+                        break;
+                    }
+                }
+            }
+            
+            XPropertySet ret = null;
+            // now describe the column name and set its related column
+            results = 
key.getTable().getConnection().getMetaData().getColumns(catalog, schema, table, 
name);
+            if (results != null) {
+                XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                if (results.next()) {
+                    if (row.getString(4).equals(name)) {
+                        int dataType = row.getInt(5);
+                        String typeName = row.getString(6);
+                        int size = row.getInt(7);
+                        int dec = row.getInt(9);
+                        int nul = row.getInt(11);
+                        String columnDef = "";
+                        try {
+                            columnDef = row.getString(13);
+                        } catch (SQLException sqlException) {
+                            // sometimes we get an error when asking for this 
param
+                        }
+                        ret = OKeyColumn.create(refColumnName, name, typeName,
+                                columnDef, nul, size, dec, dataType, false, 
false, false, isCaseSensitive());
+                        
+                    }
+                }
+            }
+            return ret;
+        } catch (WrappedTargetException | UnknownPropertyException | 
IllegalArgumentException exception) {
+            throw new SQLException("Error", this, 
StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception);
+        }
+    }
+    
+    @Override
+    public void impl_refresh() {
+    }
+    
+    @Override
+    public XPropertySet appendObject(String _rForName, XPropertySet 
descriptor) throws SQLException {
+        throw new SQLException("Cannot change a key's columns, please delete 
and re-create the key instead");
+    }
+    
+    @Override
+    public void dropObject(int index, String name) throws SQLException {
+        throw new SQLException("Cannot change a key's columns, please delete 
and re-create the key instead");
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyColumnContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyContainer.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyContainer.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyContainer.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyContainer.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,277 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNamed;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdbc.KeyRule;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbcx.KeyType;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import com.sun.star.sdbcx.comp.postgresql.sdbcx.descriptors.SdbcxKeyDescriptor;
+import com.sun.star.sdbcx.comp.postgresql.util.ComposeRule;
+import com.sun.star.sdbcx.comp.postgresql.util.DbTools;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.UnoRuntime;
+
+public class OKeyContainer extends OContainer {
+    private OTable table;
+    private Map<String,OKey> keys;
+    
+    protected OKeyContainer(Object lock, boolean isCaseSensitive, List<String> 
names, Map<String,OKey> keys, OTable table) {
+        super(lock, isCaseSensitive, names);
+        System.out.println("Keys.size()=" + keys.size());
+        for (Map.Entry<String,OKey> entry : keys.entrySet()) {
+            System.out.println(entry.getKey() + " => " + 
entry.getValue().referencedTable);
+            XIndexAccess cols = UnoRuntime.queryInterface(XIndexAccess.class, 
entry.getValue().getColumns());
+            try {
+                System.out.println("" + cols.getCount() + " columns:");
+                for (int i =0; i < cols.getCount(); i++) {
+                    System.out.println("  " + 
AnyConverter.toObject(XNamed.class, cols.getByIndex(i)).getName());
+                }
+            } catch (WrappedTargetException wrappedTargetException) {
+                wrappedTargetException.printStackTrace();
+            } catch (IndexOutOfBoundsException indexOutOfBoundsException) {
+                indexOutOfBoundsException.printStackTrace();
+            } catch (IllegalArgumentException argumentException) {
+                argumentException.printStackTrace();
+            }
+        }
+        this.keys = keys;
+        this.table = table;
+    }
+    
+    public static OKeyContainer create(boolean isCaseSensitive, 
Map<String,OKey> keys, OTable table) {
+        final Object lock = new Object();
+        String[] names = new String[keys.size()];
+        keys.keySet().toArray(names);
+        return new OKeyContainer(lock, isCaseSensitive, Arrays.asList(names), 
keys, table);
+    }
+
+    @Override
+    public XPropertySet createDescriptor() {
+        return SdbcxKeyDescriptor.create(isCaseSensitive());
+    }
+    
+    @Override
+    public XPropertySet createObject(String name) throws SQLException {
+        OKey ret = null;
+        
+        if (!name.isEmpty()) {
+            ret = keys.get(name);
+        }
+        
+        if (ret == null) { // we have a primary key with a system name
+            // FIXME: so why was this exactly the same?
+            ret = keys.get(name);
+        }
+        
+        return ret;
+    }
+    
+    @Override
+    public void impl_refresh() {
+        //throw new NotImplementedException("");
+    }
+    
+    @Override
+    public XPropertySet appendObject(String _rForName, XPropertySet 
descriptor) throws SQLException {
+        XConnection connection = table.getConnection();
+        if (connection == null) {
+            return null;
+        }
+        try {
+            int keyType = 
AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.TYPE.name));
+            int updateRule = 0;
+            int deleteRule = 0;
+            String referencedName = "";
+            if (keyType == KeyType.FOREIGN) {
+                referencedName = 
AnyConverter.toString(descriptor.getPropertyValue(PropertyIds.UPDATERULE.name));
+                updateRule = 
AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.UPDATERULE.name));
+                deleteRule = 
AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.DELETERULE.name));
+            }
+            
+            String quote = connection.getMetaData().getIdentifierQuoteString();
+            String tableName = 
DbTools.composeTableName(connection.getMetaData(), table, 
ComposeRule.InTableDefinitions, false, false, true);
+            
+            String keyTypeString;
+            if (keyType == KeyType.PRIMARY) {
+                keyTypeString = "PRIMARY KEY";
+            } else if (keyType == KeyType.FOREIGN) {
+                keyTypeString = "FOREIGN KEY";
+            } else {
+                throw new SQLException();
+            }
+            
+            StringBuilder columnsText = new StringBuilder();
+            XColumnsSupplier columnsSupplier = 
UnoRuntime.queryInterface(XColumnsSupplier.class, descriptor);
+            XIndexAccess columns = 
UnoRuntime.queryInterface(XIndexAccess.class, columnsSupplier.getColumns());
+            String separator = "";
+            for (int i = 0; i < columns.getCount(); i++) {
+                columnsText.append(separator);
+                separator = ",";
+                XPropertySet columnProperties = 
AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i));
+                columnsText.append(DbTools.quoteName(quote, 
AnyConverter.toString(columnProperties.getPropertyValue(PropertyIds.NAME.name))));
+            }
+            
+            String sql = String.format("ALTER TABLE %s ADD %s (%s)", 
tableName, keyTypeString, columnsText.toString());
+            
+            if (keyType == KeyType.FOREIGN) {
+                String quotedTableName = 
DbTools.quoteTableName(connection.getMetaData(), referencedName, 
ComposeRule.InTableDefinitions);
+                StringBuilder relatedColumns = new StringBuilder();
+                separator = "";
+                for (int i = 0; i < columns.getCount(); i++) {
+                    relatedColumns.append(separator);
+                    separator = ",";
+                    XPropertySet columnProperties = 
AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i));
+                    relatedColumns.append(DbTools.quoteName(quote, 
AnyConverter.toString(columnProperties.getPropertyValue(PropertyIds.RELATEDCOLUMN.name))));
+                }
+                sql += String.format(" REFERENCES %s (%s)%s%s", 
quotedTableName, relatedColumns.toString(),
+                        getKeyRuleString(true, updateRule), 
getKeyRuleString(false, deleteRule));
+            }
+            XStatement statement = null;
+            try {
+                statement = connection.createStatement();
+                statement.execute(sql);
+            } finally {
+                CompHelper.disposeComponent(statement);
+            }
+            
+            // find the name which the database gave the new key
+            String newName = _rForName;
+            try {
+                String schema = 
AnyConverter.toString(this.table.getPropertyValue(PropertyIds.SCHEMANAME.name));
+                String table = 
AnyConverter.toString(this.table.getPropertyValue(PropertyIds.TABLENAME.name));
+                XResultSet results = null;
+                try {
+                    final int column;
+                    if (keyType == KeyType.FOREIGN) {
+                        results = 
connection.getMetaData().getImportedKeys(this.table.getPropertyValue(PropertyIds.CATALOGNAME.name),
 schema, table);
+                        column = 12;
+                    } else {
+                        results = 
connection.getMetaData().getPrimaryKeys(this.table.getPropertyValue(PropertyIds.CATALOGNAME.name),
 schema, table);
+                        column = 6;
+                    }
+                    if (results != null) {
+                        XRow row = UnoRuntime.queryInterface(XRow.class, 
results);
+                        while (results.next()) {
+                            String name = row.getString(column);
+                            if (!hasByName(name)) { // this name wasn't 
inserted yet so it must be the new one
+                                
descriptor.setPropertyValue(PropertyIds.NAME.name, name);
+                                newName = name;
+                                break;
+                            }
+                        }
+                    }
+                } finally {
+                    CompHelper.disposeComponent(results);
+                }
+            } catch (SQLException sqlException) {
+            }
+            keys.put(newName, OKey.create(newName, isCaseSensitive(), 
referencedName, keyType, updateRule, deleteRule, new ArrayList<String>(), 
table));
+            return createObject(newName);
+        } catch (WrappedTargetException wrappedTargetException) {
+        } catch (UnknownPropertyException unknownPropertyException) {
+        } catch (IllegalArgumentException illegalArgumentException) {
+        } catch (IndexOutOfBoundsException indexOutOfBoundsException) {
+        } catch (PropertyVetoException propertyVetoException) {
+        }
+        return null;
+    }
+    
+    protected String getKeyRuleString(boolean isUpdate, int rule) {
+        String keyRule = "";
+        switch (rule) {
+        case KeyRule.CASCADE:
+            keyRule = isUpdate ? " ON UPDATE CASCADE " : " ON DELETE CASCADE ";
+            break;
+        case KeyRule.RESTRICT:
+            keyRule = isUpdate ? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT 
";
+            break;
+        case KeyRule.SET_NULL:
+            keyRule = isUpdate ? " ON UPDATE SET NULL " : " ON DELETE SET NULL 
";
+            break;
+        case KeyRule.SET_DEFAULT:
+            keyRule = isUpdate ? " ON UPDATE SET DEFAULT " : " ON DELETE SET 
DEFAULT ";
+            break;
+        }
+        return keyRule;
+    }
+    
+    @Override
+    public void dropObject(int index, String name) throws SQLException {
+        XConnection connection = table.getConnection();
+        if (connection == null) {
+            return;
+        }
+        try {
+            XPropertySet key = AnyConverter.toObject(XPropertySet.class, 
getObject(index));
+            String tableName = 
DbTools.composeTableName(connection.getMetaData(), table,
+                    ComposeRule.InTableDefinitions, false, false, true);
+            final int keyType;
+            if (key != null) {
+                keyType = 
AnyConverter.toInt(key.getPropertyValue(PropertyIds.TYPE.name));
+            } else {
+                keyType = KeyType.PRIMARY;
+            }
+            final String sql;
+            if (keyType == KeyType.PRIMARY) {
+                sql = String.format("ALTER TABLE %s DROP PRIMARY KEY", 
tableName);
+            } else {
+                sql = String.format("ALTER TABLE %s %s %s", tableName, 
getDropForeignKey(),
+                        
DbTools.quoteName(connection.getMetaData().getIdentifierQuoteString(), name));
+            }
+            XStatement statement = null;
+            try {
+                statement = connection.createStatement();
+                statement.execute(sql);
+            } finally {
+                CompHelper.disposeComponent(statement);
+            }
+        } catch (IllegalArgumentException illegalArgumentException) {
+            
+        } catch (WrappedTargetException wrappedTargetException) {
+        } catch (UnknownPropertyException unknownPropertyException) {
+        }
+    }
+    
+    public String getDropForeignKey() {
+        return "DROP CONSTRAINT";
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OKeyContainer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OTable.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OTable.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OTable.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OTable.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,187 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNamed;
+import com.sun.star.lang.DisposedException;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbcx.XAlterTable;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDataDescriptorFactory;
+import com.sun.star.sdbcx.XIndexesSupplier;
+import com.sun.star.sdbcx.XKeysSupplier;
+import com.sun.star.sdbcx.XRename;
+import 
com.sun.star.sdbcx.comp.postgresql.comphelper.PropertySetAdapter.PropertyGetter;
+import com.sun.star.sdbcx.comp.postgresql.util.PropertyIds;
+import com.sun.star.uno.Type;
+
+public abstract class OTable extends ODescriptor
+        implements XColumnsSupplier, XKeysSupplier, XNamed, XServiceInfo, 
XDataDescriptorFactory,
+            XIndexesSupplier, XRename, XAlterTable {
+
+    private static String[] services = {
+            "com.sun.star.sdbcx.Table"
+    };
+    
+    private XConnection connection;
+    protected String catalogName;
+    protected String schemaName;
+    protected String description;
+    protected String type;
+    
+    protected OContainer keys;
+    protected OContainer columns;
+    protected OContainer indexes;
+    protected OContainer tables;
+    
+    protected OTable(Object lock, String name, boolean isCaseSensitive, 
XConnection connection, OContainer tables) {
+        super(lock, name, isCaseSensitive);
+        this.tables = tables;
+        this.connection = connection;
+        registerProperties();
+    }
+    
+    private void registerProperties() {
+        registerProperty(PropertyIds.CATALOGNAME.name, 
PropertyIds.CATALOGNAME.id, Type.STRING, PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return catalogName;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.SCHEMANAME.name, 
PropertyIds.SCHEMANAME.id, Type.STRING, PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return schemaName;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.DESCRIPTION.name, 
PropertyIds.DESCRIPTION.id, Type.STRING, PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return description;
+                        
+                    }
+                }, null);
+        registerProperty(PropertyIds.TYPE.name, PropertyIds.TYPE.id, 
Type.STRING, PropertyAttribute.READONLY,
+                new PropertyGetter() {
+                    @Override
+                    public Object getValue() {
+                        return type;
+                        
+                    }
+                }, null);
+    }
+    
+    @Override
+    protected void postDisposing() {
+        super.postDisposing();
+        if (keys != null) {
+            keys.dispose();
+        }
+        if (columns != null) {
+            columns.dispose();
+        }
+        if (indexes != null) {
+            indexes.dispose();
+        }
+        tables = null;
+    }
+    
+    private void checkDisposed() {
+        if (bInDispose || bDisposed) {
+            throw new DisposedException();
+        }
+    }
+    
+    // XServiceInfo
+    
+    @Override
+    public String getImplementationName() {
+        return "com.sun.star.sdbcx.Table";
+    }
+    
+    @Override
+    public String[] getSupportedServiceNames() {
+        return services.clone();
+    }
+    
+    @Override
+    public boolean supportsService(String serviceName) {
+        for (String service : services) {
+            if (serviceName.equals(service)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    // XColumnsSupplier
+    
+    @Override
+    public XNameAccess getColumns() {
+        checkDisposed();
+        synchronized (lock) {
+            if (columns == null) {
+                columns = refreshColumns();
+            }
+            return columns;
+        }
+    }
+    
+    @Override
+    public XNameAccess getIndexes() {
+        checkDisposed();
+        synchronized (lock) {
+            if (indexes == null) {
+                indexes = refreshIndexes();
+            }
+            return indexes;
+        }
+    }
+    
+    @Override
+    public XIndexAccess getKeys() {
+        checkDisposed();
+        synchronized (lock) {
+            if (keys == null) {
+                keys = refreshKeys();
+            }
+            return keys;
+        }
+    }
+    
+    public XConnection getConnection() {
+        return connection;
+    }
+    
+    protected abstract OContainer refreshColumns();
+    protected abstract OContainer refreshIndexes();
+    protected abstract OContainer refreshKeys();
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OfficeResourceBundle.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OfficeResourceBundle.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OfficeResourceBundle.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OfficeResourceBundle.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,130 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import com.sun.star.lang.NullPointerException;
+import com.sun.star.resource.MissingResourceException;
+import com.sun.star.resource.OfficeResourceLoader;
+import com.sun.star.resource.XResourceBundle;
+import com.sun.star.resource.XResourceBundleLoader;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.XComponentContext;
+
+public class OfficeResourceBundle implements AutoCloseable {
+    
+    private XComponentContext context;
+    private String baseName;
+    private boolean haveAttemptedCreate;
+    private XResourceBundle bundle;
+    
+    
+    /** constructs a resource bundle
+        @param  context
+            the component context to operate in
+        @param  bundleBaseName
+            the base name of the resource file which should be accessed 
(*without* the SUPD!)
+        @raises ::com::sun::star::lang::NullPointerException
+            if the given component context is <NULL/>
+     */
+    public OfficeResourceBundle(XComponentContext context, String 
bundleBaseName) throws NullPointerException {
+        if (context == null) {
+            throw new NullPointerException();
+        }
+        this.context = context;
+        this.baseName = bundleBaseName;
+        this.haveAttemptedCreate = false;
+    }
+    
+    @Override
+    public void close() {
+        CompHelper.disposeComponent(bundle);
+    }
+    
+    /** loads the string with the given resource id from the resource bundle
+        @param  _resourceId
+            the id of the string to load
+        @return
+            the requested resource string. If no string with the given id 
exists in the resource bundle,
+            an empty string is returned. In a non-product version, an 
OSL_ENSURE will notify you of this
+            then.
+    */
+    public String loadString( int _resourceId ) {
+        synchronized (this) {
+            String ret = "";
+            if (loadBundle()) {
+                try {
+                    Object value = 
bundle.getByName(getStringResourceKey(_resourceId));
+                    ret = AnyConverter.toString(value);
+                } catch (com.sun.star.uno.Exception ex) {
+                }
+            }
+            return ret;
+        }
+    }
+
+    /** determines whether the resource bundle has a string with the given id
+        @param  _resourceId
+            the id of the string whose existence is to be checked
+        @return
+            <TRUE/> if and only if a string with the given ID exists in the 
resource
+            bundle.
+    */
+    public boolean hasString( int _resourceId ) {
+        synchronized (this) {
+            boolean ret = false;
+            if (loadBundle()) {
+                ret = bundle.hasByName(getStringResourceKey(_resourceId));
+            }
+            return ret;
+        }
+    }
+    
+    private String getStringResourceKey(int resourceId) {
+        return "string:" + resourceId;
+    }
+    
+    private boolean loadBundle() {
+        if (haveAttemptedCreate) {
+            return bundle != null;
+        }
+        haveAttemptedCreate = true;
+        
+        try {
+            XResourceBundleLoader loader = OfficeResourceLoader.get(context);
+            try {
+                if (loader == null) {
+                    return false;
+                }
+                try {
+                    bundle = loader.loadBundle_Default(baseName);
+                } catch (MissingResourceException missingResourceException) {
+                }
+                return bundle != null;
+            } finally {
+                CompHelper.disposeComponent(loader);
+            }
+        } catch (Exception exception) {
+        }
+        return false;
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/OfficeResourceBundle.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/Resources.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/Resources.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/Resources.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/Resources.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,66 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+public class Resources {
+    public static final int STR_COMMON_BASE = 1200;
+    
+    public static final int STR_STRING_LENGTH_EXCEEDED = (STR_COMMON_BASE + 1);
+    public static final int STR_CANNOT_CONVERT_STRING = (STR_COMMON_BASE + 2);
+    public static final int STR_URI_SYNTAX_ERROR = (STR_COMMON_BASE + 3);
+    public static final int STR_COULD_NOT_LOAD_FILE = (STR_COMMON_BASE + 4);
+    public static final int STR_QUERY_TOO_COMPLEX = (STR_COMMON_BASE + 5);
+    public static final int STR_OPERATOR_TOO_COMPLEX = (STR_COMMON_BASE + 6);
+    public static final int STR_QUERY_INVALID_LIKE_COLUMN = (STR_COMMON_BASE + 
7);
+    public static final int STR_QUERY_INVALID_LIKE_STRING = (STR_COMMON_BASE + 
8);
+    public static final int STR_QUERY_NOT_LIKE_TOO_COMPLEX = (STR_COMMON_BASE 
+ 9);
+    public static final int STR_QUERY_LIKE_WILDCARD = (STR_COMMON_BASE + 10);
+    public static final int STR_QUERY_LIKE_WILDCARD_MANY = (STR_COMMON_BASE + 
11);
+    public static final int STR_INVALID_COLUMNNAME = (STR_COMMON_BASE + 12);
+    public static final int STR_NO_CLASSNAME = (STR_COMMON_BASE + 13);
+    public static final int STR_NO_CLASSNAME_PATH = (STR_COMMON_BASE + 14);
+    public static final int STR_UNKNOWN_PARA_TYPE = (STR_COMMON_BASE + 15);
+    public static final int STR_INVALID_COLUMN_SELECTION = (STR_COMMON_BASE + 
16);
+    public static final int STR_PARA_ONLY_PREPARED = (STR_COMMON_BASE + 17);
+    public static final int STR_COLUMN_NOT_UPDATEABLE = (STR_COMMON_BASE + 18);
+    public static final int STR_ROW_ALREADY_DELETED = (STR_COMMON_BASE + 19);
+    public static final int STR_UNKNOWN_COLUMN_TYPE = (STR_COMMON_BASE + 20);
+    public static final int STR_FORMULA_WRONG = (STR_COMMON_BASE + 21);
+    public static final int STR_NO_JAVA = (STR_COMMON_BASE + 22);
+    public static final int STR_NO_RESULTSET = (STR_COMMON_BASE + 23);
+    public static final int STR_NO_ROWCOUNT = (STR_COMMON_BASE + 24);
+    public static final int STR_ERRORMSG_SEQUENCE = (STR_COMMON_BASE + 25);
+    public static final int STR_INVALID_INDEX = (STR_COMMON_BASE + 26);
+    public static final int STR_UNSUPPORTED_FUNCTION = (STR_COMMON_BASE + 27);
+    public static final int STR_UNSUPPORTED_FEATURE = (STR_COMMON_BASE + 28);
+    public static final int STR_UNKNOWN_COLUMN_NAME = (STR_COMMON_BASE + 29);
+    public static final int STR_INVALID_PARA_COUNT = (STR_COMMON_BASE + 30);
+    public static final int STR_PRIVILEGE_NOT_GRANTED = (STR_COMMON_BASE + 31);
+    public static final int STR_PRIVILEGE_NOT_REVOKED = (STR_COMMON_BASE + 32);
+    public static final int STR_INVALID_BOOKMARK = (STR_COMMON_BASE + 33);
+    public static final int STR_NO_ELEMENT_NAME = (STR_COMMON_BASE + 34);
+    public static final int STR_NO_INPUTSTREAM = (STR_COMMON_BASE + 35);
+    public static final int STR_INPUTSTREAM_WRONG_LEN = (STR_COMMON_BASE + 36);
+    public static final int STR_WRONG_PARAM_INDEX = (STR_COMMON_BASE + 37);
+    public static final int STR_NO_CONNECTION_GIVEN = (STR_COMMON_BASE + 38);
+
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/Resources.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SharedResources.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SharedResources.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SharedResources.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SharedResources.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,213 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.List;
+
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.sun.star.lang.NullPointerException;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * helper class for accessing resources shared by different libraries
+ * in the connectivity module.
+ */
+public class SharedResources {
+    private static SharedResources instance;
+    private static int referenceCount = 0;
+    
+    private OfficeResourceBundle resourceBundle;
+
+    // FIXME: the C++ implementation gets the XComponentContext using 
::comphelper::getProcessServiceFactory(), we don't.
+    public synchronized static void registerClient(XComponentContext context) {
+        if (instance == null) {
+            instance = new SharedResources(context);
+        }
+        ++referenceCount;
+    }
+    
+    public synchronized static void revokeClient() {
+        if (--referenceCount == 0) {
+            CompHelper.disposeComponent(instance);
+            instance = null;
+        }
+    }
+    
+    public synchronized static SharedResources getInstance() {
+        return instance;
+    }
+    
+    private SharedResources(XComponentContext context) {
+        try {
+            resourceBundle = new OfficeResourceBundle(context, "cnr");
+        } catch (NullPointerException nullPointerException) {
+        }
+    }
+    
+    private int substitute( MutableObject<String> _inout_rString,
+            String sPattern, String _rReplace ) {
+        int nOccurences = 0;
+        String string = _inout_rString.getValue();
+        int nIndex = 0;
+        while ( ( nIndex = string.indexOf( sPattern ) ) > -1 )
+        {
+            ++nOccurences;
+            string = string.substring(0, nIndex) +
+                    _rReplace + string.substring(nIndex + sPattern.length());
+        }
+        _inout_rString.setValue(string);
+        return nOccurences;
+    }
+
+    
+    /** loads a string from the shared resource file
+        @param  _nResId
+            the resource ID of the string
+        @return
+            the string from the resource file
+     */
+    public String
+    getResourceString(
+        int _nResId
+    ) {
+        if (resourceBundle == null) {
+            return "";
+        }
+        return resourceBundle.loadString(_nResId);
+    }
+    
+    /** loads a string from the shared resource file, and replaces
+        a given ASCII pattern with a given string
+    
+        @param  _nResId
+            the resource ID of the string to load
+        @param  _pAsciiPatternToReplace
+            the ASCII string which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute
+            the String which should substitute the ASCII pattern.
+        
+        @return
+            the string from the resource file, with applied string substitution
+     */
+    public String
+    getResourceStringWithSubstitution(
+        int _nResId,
+        String _pAsciiPatternToReplace,
+        String _rStringToSubstitute
+    ) {
+        MutableObject<String> string = new 
MutableObject<>(getResourceString(_nResId));
+        substitute(string, _pAsciiPatternToReplace, _rStringToSubstitute);
+        return string.getValue();
+    }
+    
+    /** loads a string from the shared resource file, and replaces
+        a given ASCII pattern with a given string
+    
+        @param  _nResId
+            the resource ID of the string to load
+        @param  _pAsciiPatternToReplace1
+            the ASCII string (1) which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute1
+            the String which should substitute the ASCII pattern (1)
+        @param  _pAsciiPatternToReplace2
+            the ASCII string (2) which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute2
+            the String which should substitute the ASCII pattern (2)
+        
+        @return
+            the string from the resource file, with applied string substitution
+     */
+    public String
+    getResourceStringWithSubstitution(
+        int _nResId,
+        String _pAsciiPatternToReplace1,
+        String _rStringToSubstitute1,
+        String _pAsciiPatternToReplace2,
+        String _rStringToSubstitute2
+    ) {
+        MutableObject<String> string = new 
MutableObject<>(getResourceString(_nResId));
+        substitute(string, _pAsciiPatternToReplace1, _rStringToSubstitute1);
+        substitute(string, _pAsciiPatternToReplace2, _rStringToSubstitute2);
+        return string.getValue();
+    }
+    
+    /** loads a string from the shared resource file, and replaces
+        a given ASCII pattern with a given string
+
+        @param  _nResId
+            the resource ID of the string to load
+        @param  _pAsciiPatternToReplace1
+            the ASCII string (1) which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute1
+            the String which should substitute the ASCII pattern (1)
+        @param  _pAsciiPatternToReplace2
+            the ASCII string (2) which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute2
+            the String which should substitute the ASCII pattern (2)
+        @param  _pAsciiPatternToReplace3
+            the ASCII string (3) which is to search in the string. Must not be 
<NULL/>.
+        @param  _rStringToSubstitute3
+            the String which should substitute the ASCII pattern (3)
+        
+        @return
+            the string from the resource file, with applied string substitution
+     */
+    public String
+    getResourceStringWithSubstitution(
+        int _nResId,
+        String _pAsciiPatternToReplace1,
+        String _rStringToSubstitute1,
+        String _pAsciiPatternToReplace2,
+        String _rStringToSubstitute2,
+        String _pAsciiPatternToReplace3,
+        String _rStringToSubstitute3
+    ) {
+        MutableObject<String> string = new 
MutableObject<>(getResourceString(_nResId));
+        substitute(string, _pAsciiPatternToReplace1, _rStringToSubstitute1);
+        substitute(string, _pAsciiPatternToReplace2, _rStringToSubstitute2);
+        substitute(string, _pAsciiPatternToReplace3, _rStringToSubstitute3);
+        return string.getValue();
+    }
+    
+    /** loads a string from the shared resource file, and replaces a given 
ASCII pattern with a given string
+
+        @param  _nResId
+            the resource ID of the string to load
+        @param  _aStringToSubstitutes
+            A list of substitutions.
+    
+        @return
+            the string from the resource file, with applied string substitution
+     */
+    public String
+    getResourceStringWithSubstitution( int _nResId,
+            List<Pair<String,String>> patternsAndSubstitutes) {
+        MutableObject<String> string = new 
MutableObject<>(getResourceString(_nResId));
+        for (Pair<String,String> pair : patternsAndSubstitutes) {
+            substitute(string, pair.getLeft(), pair.getRight());
+        }
+        return string.getValue();
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SharedResources.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SqlTableHelper.java
URL: 
http://svn.apache.org/viewvc/openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SqlTableHelper.java?rev=1805579&view=auto
==============================================================================
--- 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SqlTableHelper.java
 (added)
+++ 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SqlTableHelper.java
 Sun Aug 20 19:16:28 2017
@@ -0,0 +1,261 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+package com.sun.star.sdbcx.comp.postgresql.sdbcx;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XDatabaseMetaData;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbcx.KeyType;
+import com.sun.star.sdbcx.comp.postgresql.comphelper.CompHelper;
+import com.sun.star.sdbcx.comp.postgresql.util.ComposeRule;
+import com.sun.star.sdbcx.comp.postgresql.util.DbTools;
+import com.sun.star.sdbcx.comp.postgresql.util.Osl;
+import com.sun.star.uno.Any;
+import com.sun.star.uno.UnoRuntime;
+
+public class SqlTableHelper {
+    public static class ColumnDescription {
+        public String columnName;
+        public int type;
+        public String typeName;
+        public int columnSize;
+        public int decimalDigits;
+        public int nullable;
+        public String remarks;
+        public String defaultValue;
+        public int ordinalPosition;
+    }
+    
+    private static class KeyProperties {
+        ArrayList<String> columnNames = new ArrayList<>();
+        String referencedTable;
+        int type;
+        int updateRule;
+        int deleteRule;
+        
+        KeyProperties(String referencedTable, int type, int updateRule, int 
deleteRule) {
+            this.referencedTable = referencedTable;
+            this.type = type;
+            this.updateRule = updateRule;
+            this.deleteRule = deleteRule;
+        }
+    }
+    
+    public List<ColumnDescription> readColumns(XDatabaseMetaData metadata, 
String catalog, String schema, String table) throws SQLException {
+        String catalogName = catalog;
+        if (catalog.isEmpty()) {
+            catalogName = null;
+        }
+        
+        XResultSet results = metadata.getColumns(catalogName, schema, table, 
"%");
+        List<ColumnDescription> columnDescriptions = 
collectColumnDescriptions(results);
+        sanitizeColumnDescriptions(columnDescriptions);
+
+        List<ColumnDescription> columnsByOrdinal = new 
ArrayList<>(columnDescriptions);
+        for (ColumnDescription columnDescription : columnDescriptions) {
+            columnsByOrdinal.set(columnDescription.ordinalPosition - 1, 
columnDescription);
+        }
+        return columnsByOrdinal;
+    }
+    
+    private List<ColumnDescription> collectColumnDescriptions(XResultSet 
results) throws SQLException {
+        List<ColumnDescription> columns = new ArrayList<>();
+        XRow row = UnoRuntime.queryInterface(XRow.class, results);
+        while (results.next()) {
+            ColumnDescription columnDescription = new ColumnDescription();
+            columnDescription.columnName = row.getString(4);
+            columnDescription.type = row.getInt(5);
+            columnDescription.typeName = row.getString(6);
+            columnDescription.columnSize = row.getInt(7);
+            columnDescription.decimalDigits = row.getInt(9);
+            columnDescription.nullable = row.getInt(11);
+            columnDescription.remarks = row.getString(12);
+            columnDescription.defaultValue = row.getString(13);
+            columnDescription.ordinalPosition = row.getInt(17);
+            columns.add(columnDescription);
+        }
+        return columns;
+    }
+    
+    private void sanitizeColumnDescriptions(List<ColumnDescription> 
columnDescriptions) {
+        if (columnDescriptions.isEmpty()) {
+            return;
+        }
+        Set<Integer> usedOrdinals = new TreeSet<>();
+        int maxOrdinal = Integer.MIN_VALUE;
+        for (ColumnDescription columnDescription : columnDescriptions) {
+            usedOrdinals.add(columnDescription.ordinalPosition);
+            if (maxOrdinal < columnDescription.ordinalPosition) {
+                maxOrdinal = columnDescription.ordinalPosition;
+            }
+        }
+        // we need to have as many different ordinals as we have different 
columns
+        boolean hasDuplicates = usedOrdinals.size() != 
columnDescriptions.size();
+        // and it needs to be a continuous range
+        boolean hasGaps = (maxOrdinal - usedOrdinals.iterator().next() + 1) != 
columnDescriptions.size();
+        // if that's not the case, normalize it
+        Osl.ensure(!hasDuplicates && !hasGaps, "database provided invalid 
ORDINAL_POSITION values!");
+        // what's left is that the range might not be from 1 to <column 
count>, but for instance
+        // 0 to <column count>-1.
+        int offset = usedOrdinals.iterator().next() - 1;
+        for (ColumnDescription columnDescription : columnDescriptions) {
+            columnDescription.ordinalPosition -= offset;
+        }
+    }
+    
+    public Map<String, OKey> readKeys(XDatabaseMetaData metadata, String 
catalogName, String schemaName, String tableName,
+            boolean isCaseSensitive, OTable table) throws SQLException {
+        Map<String, OKey> keys = new TreeMap<>();
+        OKey primaryKey = readPrimaryKey(metadata, catalogName, schemaName, 
tableName, isCaseSensitive, table);
+        keys.put(primaryKey.getName(), primaryKey);
+        readForeignKeys(metadata, catalogName, schemaName, tableName, 
isCaseSensitive, keys, table);
+        return keys;
+    }
+    
+    private OKey readPrimaryKey(XDatabaseMetaData metadata,
+            String catalogName, String schemaName, String tableName, boolean 
isCaseSensitive, OTable table) throws SQLException {
+        Object catalog = Any.VOID;
+        if (!catalogName.isEmpty()) {
+            catalog = catalogName;
+        }
+        XResultSet results = null;
+        try {
+            ArrayList<String> columns = new ArrayList<>();
+            boolean alreadyFetched = false;
+            String pkName = "";
+            OKey key = null;
+            results = metadata.getPrimaryKeys(catalog, schemaName, tableName);
+            if (results != null) {
+                XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                while (results.next()) {
+                    String columnName = row.getString(4);
+                    columns.add(columnName);
+                    if (!alreadyFetched) {
+                        alreadyFetched = true;
+                        pkName = row.getString(6);
+                    }
+                }
+                key = OKey.create(pkName, isCaseSensitive, "", 
KeyType.PRIMARY, 0, 0, columns, table);
+            }
+            return key;
+        } finally {
+            CompHelper.disposeComponent(results);
+        }
+    }
+    
+    private void readForeignKeys(XDatabaseMetaData metadata,
+            String catalogName, String schemaName, String tableName, boolean 
isCaseSensitive, Map<String, OKey> keys, OTable table) throws SQLException {
+        Object catalog = Any.VOID;
+        if (!catalogName.isEmpty()) {
+            catalog = catalogName;
+        }
+        XResultSet results = null;
+        try {
+            results = metadata.getImportedKeys(catalog, schemaName, tableName);
+            XRow row = UnoRuntime.queryInterface(XRow.class, results);
+            if (row != null) {
+                String oldFkName = "";
+                KeyProperties keyProperties = null;
+                while (results.next()) {
+                    String catalogReturned = row.getString(1);
+                    if (row.wasNull()) {
+                        catalogReturned = "";
+                    }
+                    String schemaReturned = row.getString(2);
+                    String nameReturned = row.getString(3);
+                    
+                    String foreignKeyColumn = row.getString(8);
+                    int updateRule = row.getInt(10);
+                    int deleteRule = row.getInt(11);
+                    String fkName = row.getString(12);
+                    
+                    if (!row.wasNull() && !fkName.isEmpty()) {
+                        if (!oldFkName.equals(fkName)) {
+                            if (keyProperties != null) {
+                                OKey key = OKey.create(oldFkName, 
isCaseSensitive, keyProperties.referencedTable, keyProperties.type,
+                                        keyProperties.updateRule, 
keyProperties.deleteRule, keyProperties.columnNames, table);
+                                keys.put(oldFkName, key);
+                            }
+                            String referencedName = 
DbTools.composeTableName(metadata, catalogReturned, schemaReturned, 
nameReturned,
+                                    false, ComposeRule.InDataManipulation);
+                            keyProperties = new KeyProperties(referencedName, 
KeyType.FOREIGN, updateRule, deleteRule);
+                            keyProperties.columnNames.add(foreignKeyColumn);
+                            oldFkName = fkName;
+                        } else {
+                            if (keyProperties != null) {
+                                
keyProperties.columnNames.add(foreignKeyColumn);
+                            }
+                        }
+                    }
+                }
+                if (keyProperties != null) {
+                    OKey key = OKey.create(oldFkName, isCaseSensitive, 
keyProperties.referencedTable, keyProperties.type,
+                            keyProperties.updateRule, 
keyProperties.deleteRule, keyProperties.columnNames, table);
+                    keys.put(oldFkName, key);
+                }
+            }
+        } finally {
+            CompHelper.disposeComponent(results);
+        }
+    }
+    
+    public ArrayList<String> readIndexes(XDatabaseMetaData metadata, String 
catalogName, String schemaName, String tableName, OTable table) throws 
SQLException {
+        Object catalog = Any.VOID;
+        if (!catalogName.isEmpty()) {
+            catalog = catalogName;
+        }
+        ArrayList<String> names = new ArrayList<>();
+        XResultSet results = null;
+        try {
+            results = metadata.getIndexInfo(catalog, schemaName, tableName, 
false, false);
+            if (results != null) {
+                XRow row = UnoRuntime.queryInterface(XRow.class, results);
+                String catalogSep = metadata.getCatalogSeparator();
+                String previousRoundName = "";
+                while (results.next()) {
+                    String name = row.getString(5);
+                    if (!name.isEmpty()) {
+                        name += catalogSep;
+                    }
+                    name += row.getString(6);
+                    if (!name.isEmpty()) {
+                        // don't insert the name if the last one we inserted 
was the same
+                        if (!previousRoundName.equals(name)) {
+                            names.add(name);
+                        }
+                    }
+                }
+            }
+        } finally {
+            CompHelper.disposeComponent(results);
+        }
+        return names;
+    }
+}

Propchange: 
openoffice/trunk/main/connectivity/java/sdbc_postgresql/src/com/sun/star/sdbcx/comp/postgresql/sdbcx/SqlTableHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to