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.HashMap; 26 import java.util.List; 27 import java.util.Map; 28 29 import org.apache.openoffice.comp.sdbc.dbtools.comphelper.CompHelper; 30 import org.apache.openoffice.comp.sdbc.dbtools.sdbcx.SqlTableHelper.ColumnDescription; 31 import org.apache.openoffice.comp.sdbc.dbtools.sdbcx.descriptors.SdbcxColumnDescriptor; 32 import org.apache.openoffice.comp.sdbc.dbtools.util.ComposeRule; 33 import org.apache.openoffice.comp.sdbc.dbtools.util.DbTools; 34 import org.apache.openoffice.comp.sdbc.dbtools.util.Osl; 35 36 import com.sun.star.beans.XPropertySet; 37 import com.sun.star.container.ElementExistException; 38 import com.sun.star.container.XNameAccess; 39 import com.sun.star.sdbc.ColumnValue; 40 import com.sun.star.sdbc.DataType; 41 import com.sun.star.sdbc.SQLException; 42 import com.sun.star.sdbc.XDatabaseMetaData; 43 import com.sun.star.sdbc.XStatement; 44 import com.sun.star.uno.UnoRuntime; 45 46 public class OColumnContainer extends OContainer { 47 private OTable table; 48 private XDatabaseMetaData metadata; 49 private Map<String,ColumnDescription> columnDescriptions = new HashMap<>(); 50 private Map<String,ExtraColumnInfo> extraColumnInfo = new HashMap<>(); 51 52 /// The XDatabaseMetaData.getColumns() data stored in columnDescriptions doesn't provide everything we need, so this class stores the rest. 53 public static class ExtraColumnInfo { 54 public boolean isAutoIncrement; 55 public boolean isCurrency; 56 public int dataType; 57 } 58 OColumnContainer(Object lock, boolean isCaseSensitive, List<ColumnDescription> columnDescriptions, OTable table, XDatabaseMetaData metadata)59 public OColumnContainer(Object lock, boolean isCaseSensitive, List<ColumnDescription> columnDescriptions, OTable table, XDatabaseMetaData metadata) 60 throws ElementExistException { 61 super(lock, isCaseSensitive, toColumnNames(columnDescriptions)); 62 this.table = table; 63 this.metadata = metadata; 64 for (ColumnDescription columnDescription : columnDescriptions) { 65 this.columnDescriptions.put(columnDescription.columnName, columnDescription); 66 } 67 } 68 toColumnNames(List<ColumnDescription> columns)69 private static List<String> toColumnNames(List<ColumnDescription> columns) { 70 List<String> columnNames = new ArrayList<>(columns.size()); 71 for (ColumnDescription columnDescription : columns) { 72 columnNames.add(columnDescription.columnName); 73 } 74 return columnNames; 75 } 76 77 @Override createObject(String name)78 protected XPropertySet createObject(String name) throws SQLException { 79 boolean queryInfo = true; 80 boolean isAutoIncrement = false; 81 boolean isCurrency = false; 82 int dataType = DataType.OTHER; 83 84 ColumnDescription columnDescription = columnDescriptions.get(name); 85 if (columnDescription == null) { 86 // could be a recently added column. Refresh: 87 List<ColumnDescription> newColumns = new SqlTableHelper().readColumns(metadata, table.catalogName, table.schemaName, table.getName()); 88 for (ColumnDescription newColumnDescription : newColumns) { 89 if (newColumnDescription.columnName.equals(name)) { 90 columnDescriptions.put(name, newColumnDescription); 91 break; 92 } 93 } 94 columnDescription = columnDescriptions.get(name); 95 } 96 if (columnDescription == null) { 97 throw new SQLException("No column " + name + " found"); 98 } 99 100 ExtraColumnInfo columnInfo = extraColumnInfo.get(name); 101 if (columnInfo == null) { 102 String composedName = DbTools.composeTableNameForSelect(metadata.getConnection(), table); 103 extraColumnInfo = DbTools.collectColumnInformation(metadata.getConnection(), composedName, "*"); 104 columnInfo = extraColumnInfo.get(name); 105 } 106 if (columnInfo != null) { 107 queryInfo = false; 108 isAutoIncrement = columnInfo.isAutoIncrement; 109 isCurrency = columnInfo.isCurrency; 110 dataType = columnInfo.dataType; 111 } 112 113 XNameAccess primaryKeyColumns = DbTools.getPrimaryKeyColumns(UnoRuntime.queryInterface(XPropertySet.class, table)); 114 int nullable = columnDescription.nullable; 115 if (nullable != ColumnValue.NO_NULLS && primaryKeyColumns != null && primaryKeyColumns.hasByName(name)) { 116 nullable = ColumnValue.NO_NULLS; 117 } 118 return new OColumn(name, columnDescription.typeName, columnDescription.defaultValue, columnDescription.remarks, 119 nullable, columnDescription.columnSize, columnDescription.decimalDigits, columnDescription.type, 120 isAutoIncrement, false, isCurrency, isCaseSensitive()); 121 } 122 123 @Override createDescriptor()124 protected XPropertySet createDescriptor() { 125 return new SdbcxColumnDescriptor(isCaseSensitive()); 126 } 127 128 @Override impl_refresh()129 protected void impl_refresh() { 130 extraColumnInfo.clear(); 131 // FIXME: won't help 132 table.refreshColumns(); 133 } 134 135 @Override appendObject(String _rForName, XPropertySet descriptor)136 protected XPropertySet appendObject(String _rForName, XPropertySet descriptor) throws SQLException { 137 if (table == null) { 138 return cloneDescriptor(descriptor); 139 } 140 String sql = String.format("ALTER TABLE %s ADD %s", 141 DbTools.composeTableName(metadata, table, ComposeRule.InTableDefinitions, false, false, true), 142 DbTools.createStandardColumnPart(descriptor, table.getConnection(), null, table.getTypeCreatePattern())); 143 XStatement statement = null; 144 try { 145 statement = table.getConnection().createStatement(); 146 statement.execute(sql); 147 } finally { 148 CompHelper.disposeComponent(statement); 149 } 150 return createObject(_rForName); 151 } 152 153 @Override dropObject(int index, String name)154 protected void dropObject(int index, String name) throws SQLException { 155 Osl.ensure(table, "Table is null!"); 156 if (table == null) { 157 return; 158 } 159 String quote = metadata.getIdentifierQuoteString(); 160 String sql = String.format("ALTER TABLE %s DROP %s", 161 DbTools.composeTableName(metadata, table, ComposeRule.InTableDefinitions, false, false, true), 162 DbTools.quoteName(quote, name)); 163 XStatement statement = null; 164 try { 165 statement = table.getConnection().createStatement(); 166 statement.execute(sql); 167 } finally { 168 CompHelper.disposeComponent(statement); 169 } 170 } 171 } 172