1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 package org.apache.openoffice.comp.sdbc.dbtools.sdbcx; 23 24 import java.util.ArrayList; 25 import java.util.List; 26 27 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.CompHelper; 28 import org.apache.openoffice.comp.sdbc.dbtools.sdbcx.descriptors.SdbcxIndexDescriptor; 29 import org.apache.openoffice.comp.sdbc.dbtools.util.ComposeRule; 30 import org.apache.openoffice.comp.sdbc.dbtools.util.DbTools; 31 import org.apache.openoffice.comp.sdbc.dbtools.util.PropertyIds; 32 import org.apache.openoffice.comp.sdbc.dbtools.util.StandardSQLState; 33 34 import com.sun.star.beans.UnknownPropertyException; 35 import com.sun.star.beans.XPropertySet; 36 import com.sun.star.container.ElementExistException; 37 import com.sun.star.container.XIndexAccess; 38 import com.sun.star.lang.IllegalArgumentException; 39 import com.sun.star.lang.IndexOutOfBoundsException; 40 import com.sun.star.lang.WrappedTargetException; 41 import com.sun.star.sdbc.IndexType; 42 import com.sun.star.sdbc.SQLException; 43 import com.sun.star.sdbc.XConnection; 44 import com.sun.star.sdbc.XDatabaseMetaData; 45 import com.sun.star.sdbc.XResultSet; 46 import com.sun.star.sdbc.XRow; 47 import com.sun.star.sdbc.XStatement; 48 import com.sun.star.sdbcx.XColumnsSupplier; 49 import com.sun.star.uno.AnyConverter; 50 import com.sun.star.uno.UnoRuntime; 51 52 public class OIndexContainer extends OContainer { 53 protected OTable table; 54 OIndexContainer(Object lock, List<String> names, boolean isCaseSensitive, OTable table)55 public OIndexContainer(Object lock, List<String> names, boolean isCaseSensitive, OTable table) throws ElementExistException { 56 super(lock, isCaseSensitive, names); 57 this.table = table; 58 } 59 60 @Override createDescriptor()61 protected XPropertySet createDescriptor() { 62 return new SdbcxIndexDescriptor(isCaseSensitive()); 63 } 64 65 @Override createObject(String name)66 protected XPropertySet createObject(String name) throws SQLException { 67 try { 68 XConnection connection = table.getConnection(); 69 if (connection == null) { 70 return null; 71 } 72 73 XPropertySet ret = null; 74 String qualifier = ""; 75 String subname; 76 int len = name.indexOf('.'); 77 if (len >= 0) { 78 qualifier = name.substring(0, len); 79 subname = name.substring(len + 1); 80 } else { 81 subname = name; 82 } 83 84 Object catalog = table.getPropertyValue(PropertyIds.CATALOGNAME.name); 85 String schemaName = AnyConverter.toString(table.getPropertyValue(PropertyIds.SCHEMANAME.name)); 86 String tableName = AnyConverter.toString(table.getPropertyValue(PropertyIds.NAME.name)); 87 XResultSet results = null; 88 try { 89 results = connection.getMetaData().getIndexInfo(catalog, schemaName, tableName, false, false); 90 if (results != null) { 91 XRow row = UnoRuntime.queryInterface(XRow.class, results); 92 boolean found = false; 93 boolean isUnique = false; 94 int clustered = -1; 95 boolean isPrimaryKeyIndex = false; 96 ArrayList<String> columnNames = new ArrayList<>(); 97 while (results.next()) { 98 isUnique = !row.getBoolean(4); 99 if ((qualifier.isEmpty() || row.getString(5).equals(qualifier)) && row.getString(6).equals(subname)) { 100 found = true; 101 clustered = row.getShort(7); 102 isPrimaryKeyIndex = isPrimaryKeyIndex(connection.getMetaData(), catalog, schemaName, tableName, subname); 103 String columnName = row.getString(9); 104 if (!row.wasNull()) { 105 columnNames.add(columnName); 106 } 107 } 108 } 109 if (found) { 110 ret = new OIndex(subname, isCaseSensitive(), qualifier, isUnique, isPrimaryKeyIndex, clustered == IndexType.CLUSTERED, 111 columnNames, table); 112 } 113 } 114 } finally { 115 CompHelper.disposeComponent(results); 116 } 117 return ret; 118 } catch (WrappedTargetException | UnknownPropertyException | IllegalArgumentException | ElementExistException exception) { 119 throw new SQLException("Error", this, StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception); 120 } 121 } 122 isPrimaryKeyIndex(XDatabaseMetaData metadata, Object catalog, String schema, String table, String name)123 private static boolean isPrimaryKeyIndex(XDatabaseMetaData metadata, Object catalog, String schema, String table, String name) throws SQLException { 124 XResultSet results = null; 125 try { 126 results = metadata.getPrimaryKeys(catalog, schema, table); 127 if (results != null) { 128 XRow row = UnoRuntime.queryInterface(XRow.class, results); 129 if (results.next()) { // there can be only one primary key 130 return row.getString(6).equals(name); 131 } 132 } 133 return false; 134 } finally { 135 CompHelper.disposeComponent(results); 136 } 137 } 138 139 @Override appendObject(String _rForName, XPropertySet descriptor)140 protected XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException { 141 try { 142 XConnection connection = table.getConnection(); 143 if (connection == null) { 144 return null; 145 } 146 String quote = connection.getMetaData().getIdentifierQuoteString(); 147 boolean isUnique = AnyConverter.toBoolean(descriptor.getPropertyValue(PropertyIds.ISUNIQUE.name)); 148 String composedName = DbTools.composeTableName(connection.getMetaData(), table, ComposeRule.InIndexDefinitions, false, false, true); 149 StringBuilder columnsText = new StringBuilder(); 150 String separator = ""; 151 XColumnsSupplier columnsSupplier = UnoRuntime.queryInterface(XColumnsSupplier.class, descriptor); 152 XIndexAccess columns = UnoRuntime.queryInterface(XIndexAccess.class, columnsSupplier.getColumns()); 153 for (int i = 0; i < columns.getCount(); i++) { 154 columnsText.append(separator); 155 separator = ", "; 156 XPropertySet column = AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i)); 157 columnsText.append(DbTools.quoteName(quote, AnyConverter.toString(column.getPropertyValue(PropertyIds.NAME.name)))); 158 // FIXME: ::dbtools::getBooleanDataSourceSetting( m_pTable->getConnection(), "AddIndexAppendix" ); 159 boolean isAscending = AnyConverter.toBoolean(column.getPropertyValue(PropertyIds.ISASCENDING.name)); 160 columnsText.append(isAscending ? " ASC" : " DESC"); 161 } 162 String sql = String.format("CREATE %s INDEX %s ON %s (%s)", 163 isUnique ? "UNIQUE" : "", 164 _rForName.isEmpty() ? "" : DbTools.quoteName(quote, _rForName), 165 composedName, 166 columnsText.toString()); 167 XStatement statement = null; 168 try { 169 statement = connection.createStatement(); 170 statement.execute(sql); 171 } finally { 172 CompHelper.disposeComponent(statement); 173 } 174 return createObject(_rForName); 175 } catch (WrappedTargetException | UnknownPropertyException | IllegalArgumentException | IndexOutOfBoundsException exception) { 176 throw new SQLException("Error", this, StandardSQLState.SQL_GENERAL_ERROR.text(), 0, exception); 177 } 178 } 179 180 @Override dropObject(int index, String elementName)181 protected void dropObject(int index, String elementName) throws SQLException { 182 XConnection connection = table.getConnection(); 183 if (connection == null) { 184 return; 185 } 186 String name; 187 String schema = ""; 188 int len = elementName.indexOf('.'); 189 if (len >= 0) { 190 schema = elementName.substring(0, len); 191 } 192 name = elementName.substring(len + 1); 193 194 String composedName = DbTools.composeTableName(connection.getMetaData(), table, ComposeRule.InTableDefinitions, false, false, true); 195 String indexName = DbTools.composeTableName(connection.getMetaData(), "", schema, name, true, ComposeRule.InIndexDefinitions); 196 String sql = String.format("DROP INDEX %s ON %s", indexName, composedName); 197 XStatement statement = null; 198 try { 199 statement = connection.createStatement(); 200 statement.execute(sql); 201 } finally { 202 CompHelper.disposeComponent(statement); 203 } 204 } 205 206 @Override impl_refresh()207 protected void impl_refresh() { 208 // FIXME 209 } 210 } 211