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.Arrays; 26 import java.util.Map; 27 28 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.CompHelper; 29 import org.apache.openoffice.comp.sdbc.dbtools.sdbcx.descriptors.SdbcxKeyDescriptor; 30 import org.apache.openoffice.comp.sdbc.dbtools.util.ComposeRule; 31 import org.apache.openoffice.comp.sdbc.dbtools.util.DbTools; 32 import org.apache.openoffice.comp.sdbc.dbtools.util.PropertyIds; 33 34 import com.sun.star.beans.PropertyVetoException; 35 import com.sun.star.beans.UnknownPropertyException; 36 import com.sun.star.beans.XPropertySet; 37 import com.sun.star.container.ElementExistException; 38 import com.sun.star.container.XIndexAccess; 39 import com.sun.star.container.XNamed; 40 import com.sun.star.lang.IllegalArgumentException; 41 import com.sun.star.lang.IndexOutOfBoundsException; 42 import com.sun.star.lang.WrappedTargetException; 43 import com.sun.star.sdbc.KeyRule; 44 import com.sun.star.sdbc.SQLException; 45 import com.sun.star.sdbc.XConnection; 46 import com.sun.star.sdbc.XResultSet; 47 import com.sun.star.sdbc.XRow; 48 import com.sun.star.sdbc.XStatement; 49 import com.sun.star.sdbcx.KeyType; 50 import com.sun.star.sdbcx.XColumnsSupplier; 51 import com.sun.star.uno.AnyConverter; 52 import com.sun.star.uno.UnoRuntime; 53 54 public class OKeyContainer extends OContainer { 55 private OTable table; 56 private Map<String,OKey> keys; 57 OKeyContainer(Object lock, boolean isCaseSensitive, Map<String,OKey> keys, OTable table)58 public OKeyContainer(Object lock, boolean isCaseSensitive, Map<String,OKey> keys, OTable table) throws ElementExistException { 59 super(lock, isCaseSensitive, Arrays.asList(keys.keySet().toArray(new String[keys.size()]))); 60 System.out.println("Keys.size()=" + keys.size()); 61 for (Map.Entry<String,OKey> entry : keys.entrySet()) { 62 System.out.println(entry.getKey() + " => " + entry.getValue().referencedTable); 63 XIndexAccess cols = UnoRuntime.queryInterface(XIndexAccess.class, entry.getValue().getColumns()); 64 try { 65 System.out.println("" + cols.getCount() + " columns:"); 66 for (int i =0; i < cols.getCount(); i++) { 67 System.out.println(" " + AnyConverter.toObject(XNamed.class, cols.getByIndex(i)).getName()); 68 } 69 } catch (WrappedTargetException wrappedTargetException) { 70 wrappedTargetException.printStackTrace(); 71 } catch (IndexOutOfBoundsException indexOutOfBoundsException) { 72 indexOutOfBoundsException.printStackTrace(); 73 } catch (IllegalArgumentException argumentException) { 74 argumentException.printStackTrace(); 75 } 76 } 77 this.keys = keys; 78 this.table = table; 79 } 80 81 @Override createDescriptor()82 protected XPropertySet createDescriptor() { 83 return new SdbcxKeyDescriptor(isCaseSensitive()); 84 } 85 86 @Override createObject(String name)87 protected XPropertySet createObject(String name) throws SQLException { 88 OKey ret = null; 89 90 if (!name.isEmpty()) { 91 ret = keys.get(name); 92 } 93 94 if (ret == null) { // we have a primary key with a system name 95 // FIXME: so why was this exactly the same? 96 ret = keys.get(name); 97 } 98 99 return ret; 100 } 101 102 @Override impl_refresh()103 protected void impl_refresh() { 104 //throw new NotImplementedException(""); 105 } 106 107 @Override appendObject(String _rForName, XPropertySet descriptor)108 protected XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException { 109 XConnection connection = table.getConnection(); 110 if (connection == null) { 111 return null; 112 } 113 try { 114 int keyType = AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.TYPE.name)); 115 int updateRule = 0; 116 int deleteRule = 0; 117 String referencedName = ""; 118 if (keyType == KeyType.FOREIGN) { 119 referencedName = AnyConverter.toString(descriptor.getPropertyValue(PropertyIds.UPDATERULE.name)); 120 updateRule = AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.UPDATERULE.name)); 121 deleteRule = AnyConverter.toInt(descriptor.getPropertyValue(PropertyIds.DELETERULE.name)); 122 } 123 124 String quote = connection.getMetaData().getIdentifierQuoteString(); 125 String tableName = DbTools.composeTableName(connection.getMetaData(), table, ComposeRule.InTableDefinitions, false, false, true); 126 127 String keyTypeString; 128 if (keyType == KeyType.PRIMARY) { 129 keyTypeString = "PRIMARY KEY"; 130 } else if (keyType == KeyType.FOREIGN) { 131 keyTypeString = "FOREIGN KEY"; 132 } else { 133 throw new SQLException(); 134 } 135 136 StringBuilder columnsText = new StringBuilder(); 137 XColumnsSupplier columnsSupplier = UnoRuntime.queryInterface(XColumnsSupplier.class, descriptor); 138 XIndexAccess columns = UnoRuntime.queryInterface(XIndexAccess.class, columnsSupplier.getColumns()); 139 String separator = ""; 140 for (int i = 0; i < columns.getCount(); i++) { 141 columnsText.append(separator); 142 separator = ","; 143 XPropertySet columnProperties = AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i)); 144 columnsText.append(DbTools.quoteName(quote, AnyConverter.toString(columnProperties.getPropertyValue(PropertyIds.NAME.name)))); 145 } 146 147 String sql = String.format("ALTER TABLE %s ADD %s (%s)", tableName, keyTypeString, columnsText.toString()); 148 149 if (keyType == KeyType.FOREIGN) { 150 String quotedTableName = DbTools.quoteTableName(connection.getMetaData(), referencedName, ComposeRule.InTableDefinitions); 151 StringBuilder relatedColumns = new StringBuilder(); 152 separator = ""; 153 for (int i = 0; i < columns.getCount(); i++) { 154 relatedColumns.append(separator); 155 separator = ","; 156 XPropertySet columnProperties = AnyConverter.toObject(XPropertySet.class, columns.getByIndex(i)); 157 relatedColumns.append(DbTools.quoteName(quote, AnyConverter.toString(columnProperties.getPropertyValue(PropertyIds.RELATEDCOLUMN.name)))); 158 } 159 sql += String.format(" REFERENCES %s (%s)%s%s", quotedTableName, relatedColumns.toString(), 160 getKeyRuleString(true, updateRule), getKeyRuleString(false, deleteRule)); 161 } 162 XStatement statement = null; 163 try { 164 statement = connection.createStatement(); 165 statement.execute(sql); 166 } finally { 167 CompHelper.disposeComponent(statement); 168 } 169 170 // find the name which the database gave the new key 171 String newName = _rForName; 172 try { 173 String schema = AnyConverter.toString(this.table.getPropertyValue(PropertyIds.SCHEMANAME.name)); 174 String table = AnyConverter.toString(this.table.getPropertyValue(PropertyIds.TABLENAME.name)); 175 XResultSet results = null; 176 try { 177 final int column; 178 if (keyType == KeyType.FOREIGN) { 179 results = connection.getMetaData().getImportedKeys(this.table.getPropertyValue(PropertyIds.CATALOGNAME.name), schema, table); 180 column = 12; 181 } else { 182 results = connection.getMetaData().getPrimaryKeys(this.table.getPropertyValue(PropertyIds.CATALOGNAME.name), schema, table); 183 column = 6; 184 } 185 if (results != null) { 186 XRow row = UnoRuntime.queryInterface(XRow.class, results); 187 while (results.next()) { 188 String name = row.getString(column); 189 if (!hasByName(name)) { // this name wasn't inserted yet so it must be the new one 190 descriptor.setPropertyValue(PropertyIds.NAME.name, name); 191 newName = name; 192 break; 193 } 194 } 195 } 196 } finally { 197 CompHelper.disposeComponent(results); 198 } 199 } catch (SQLException sqlException) { 200 } 201 keys.put(newName, new OKey(newName, isCaseSensitive(), referencedName, keyType, updateRule, deleteRule, new ArrayList<String>(), table)); 202 return createObject(newName); 203 } catch (WrappedTargetException wrappedTargetException) { 204 } catch (UnknownPropertyException unknownPropertyException) { 205 } catch (IllegalArgumentException illegalArgumentException) { 206 } catch (IndexOutOfBoundsException indexOutOfBoundsException) { 207 } catch (PropertyVetoException propertyVetoException) { 208 } catch (ElementExistException elementExistException) { 209 } 210 return null; 211 } 212 getKeyRuleString(boolean isUpdate, int rule)213 protected String getKeyRuleString(boolean isUpdate, int rule) { 214 String keyRule = ""; 215 switch (rule) { 216 case KeyRule.CASCADE: 217 keyRule = isUpdate ? " ON UPDATE CASCADE " : " ON DELETE CASCADE "; 218 break; 219 case KeyRule.RESTRICT: 220 keyRule = isUpdate ? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT "; 221 break; 222 case KeyRule.SET_NULL: 223 keyRule = isUpdate ? " ON UPDATE SET NULL " : " ON DELETE SET NULL "; 224 break; 225 case KeyRule.SET_DEFAULT: 226 keyRule = isUpdate ? " ON UPDATE SET DEFAULT " : " ON DELETE SET DEFAULT "; 227 break; 228 } 229 return keyRule; 230 } 231 232 @Override dropObject(int index, String name)233 protected void dropObject(int index, String name) throws SQLException { 234 XConnection connection = table.getConnection(); 235 if (connection == null) { 236 return; 237 } 238 try { 239 XPropertySet key = AnyConverter.toObject(XPropertySet.class, getObject(index)); 240 String tableName = DbTools.composeTableName(connection.getMetaData(), table, 241 ComposeRule.InTableDefinitions, false, false, true); 242 final int keyType; 243 if (key != null) { 244 keyType = AnyConverter.toInt(key.getPropertyValue(PropertyIds.TYPE.name)); 245 } else { 246 keyType = KeyType.PRIMARY; 247 } 248 final String sql; 249 if (keyType == KeyType.PRIMARY) { 250 sql = String.format("ALTER TABLE %s DROP PRIMARY KEY", tableName); 251 } else { 252 sql = String.format("ALTER TABLE %s %s %s", tableName, getDropForeignKey(), 253 DbTools.quoteName(connection.getMetaData().getIdentifierQuoteString(), name)); 254 } 255 XStatement statement = null; 256 try { 257 statement = connection.createStatement(); 258 statement.execute(sql); 259 } finally { 260 CompHelper.disposeComponent(statement); 261 } 262 } catch (IllegalArgumentException illegalArgumentException) { 263 264 } catch (WrappedTargetException wrappedTargetException) { 265 } catch (UnknownPropertyException unknownPropertyException) { 266 } 267 } 268 getDropForeignKey()269 public String getDropForeignKey() { 270 return "DROP CONSTRAINT"; 271 } 272 } 273