/*
* Copyright 2007-2010 Brian S O'Neill
*
* Licensed 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 org.cojen.dirmi.jdbc;
import java.io.Serializable;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Serializable copy of a ResultSetMetaData.
*
* @author Brian S O'Neill
*/
public class ResultSetMetaDataCopy implements ResultSetMetaData, Serializable {
private static final int
NULLABLE_FLAG = (3 << 0), // requires two bits
AUTO_INCREMENT_FLAG = (1 << 2),
CASE_SENSITIVE_FLAG = (1 << 3),
SEARCHABLE_FLAG = (1 << 4),
CURRENCY_FLAG = (1 << 5),
SIGNED_FLAG = (1 << 6),
READ_ONLY_FLAG = (1 << 7),
WRITABLE_FLAG = (1 << 8),
DEFINITELY_WRITABLE_FLAG = (1 << 9);
private final int mCount;
private final int[] mFlags;
private final int[] mDisplaySizes;
private final String[] mLabels;
private final String[] mNames;
private final String[] mSchemaNames;
private final int[] mPrecisions;
private final int[] mScales;
private final String[] mTableNames;
private final String[] mCatalogNames;
private final int[] mTypes;
private final String[] mTypeNames;
private final String[] mClassNames;
private Map<String, Integer> mColumnMap;
public ResultSetMetaDataCopy(ResultSetMetaData md) throws SQLException {
final int count = md.getColumnCount();
final int[] flags = new int[count];
final int[] displaySizes = new int[count];
final String[] labels = new String[count];
final String[] names = new String[count];
final String[] schemaNames = new String[count];
final int[] precisions = new int[count];
final int[] scales = new int[count];
final String[] tableNames = new String[count];
final String[] catalogNames = new String[count];
final int[] types = new int[count];
final String[] typeNames = new String[count];
final String[] classNames = new String[count];
for (int i=0; i<count; i++) {
{
int flag = md.isNullable(i + 1);
if (md .isAutoIncrement(i + 1)) flag |= AUTO_INCREMENT_FLAG;
if (md .isCaseSensitive(i + 1)) flag |= CASE_SENSITIVE_FLAG;
if (md .isSearchable(i + 1)) flag |= SEARCHABLE_FLAG;
if (md .isCurrency(i + 1)) flag |= CURRENCY_FLAG;
if (md .isSigned(i + 1)) flag |= SIGNED_FLAG;
if (md .isReadOnly(i + 1)) flag |= READ_ONLY_FLAG;
if (md .isWritable(i + 1)) flag |= WRITABLE_FLAG;
if (md.isDefinitelyWritable(i + 1)) flag |= DEFINITELY_WRITABLE_FLAG;
flags[i] = flag;
}
displaySizes[i] = md.getColumnDisplaySize(i + 1);
labels[i] = md.getColumnLabel(i + 1);
names[i] = md.getColumnName(i + 1);
schemaNames[i] = md.getSchemaName(i + 1);
try {
precisions[i] = md.getPrecision(i + 1);
} catch (NumberFormatException e) {
// Workaround Oracle driver bug.
}
scales[i] = md.getScale(i + 1);
tableNames[i] = md.getTableName(i + 1);
catalogNames[i] = md.getCatalogName(i + 1);
types[i] = md.getColumnType(i + 1);
typeNames[i] = md.getColumnTypeName(i + 1);
classNames[i] = md.getColumnClassName(i + 1);
}
mCount = count;
mFlags = flags;
mDisplaySizes = displaySizes;
mLabels = labels;
mNames = names;
mSchemaNames = schemaNames;
mPrecisions = precisions;
mScales = scales;
mTableNames = tableNames;
mCatalogNames = catalogNames;
mTypes = types;
mTypeNames = typeNames;
mClassNames = classNames;
}
public int findColumn(String columnName) throws SQLException {
Map<String, Integer> columnMap = mColumnMap;
if (columnMap == null) {
columnMap = new LinkedHashMap<String, Integer>();
String[] names = mNames;
for (int i=0; i<names.length; i++) {
columnMap.put(names[i], i + 1);
}
mColumnMap = columnMap;
}
Integer column = columnMap.get(columnName);
if (column == null) {
throw new SQLException
("Column \"" + columnName + "\" not in result set: " + columnMap.keySet());
}
return column;
}
public int getColumnCount() {
return mCount;
}
public int isNullable(int column) {
return mFlags[column - 1] & NULLABLE_FLAG;
}
public boolean isAutoIncrement(int column) {
return (mFlags[column - 1] & AUTO_INCREMENT_FLAG) != 0;
}
public boolean isCaseSensitive(int column) {
return (mFlags[column - 1] & CASE_SENSITIVE_FLAG) != 0;
}
public boolean isSearchable(int column) {
return (mFlags[column - 1] & SEARCHABLE_FLAG) != 0;
}
public boolean isCurrency(int column) {
return (mFlags[column - 1] & CURRENCY_FLAG) != 0;
}
public boolean isSigned(int column) {
return (mFlags[column - 1] & SIGNED_FLAG) != 0;
}
public boolean isReadOnly(int column) {
return (mFlags[column - 1] & READ_ONLY_FLAG) != 0;
}
public boolean isWritable(int column) {
return (mFlags[column - 1] & WRITABLE_FLAG) != 0;
}
public boolean isDefinitelyWritable(int column) {
return (mFlags[column - 1] & DEFINITELY_WRITABLE_FLAG) != 0;
}
public int getColumnDisplaySize(int column) {
return mDisplaySizes[column - 1];
}
public String getColumnLabel(int column) {
return mLabels[column - 1];
}
public String getColumnName(int column) {
return mNames[column - 1];
}
public String getSchemaName(int column) {
return mSchemaNames[column - 1];
}
public int getPrecision(int column) {
return mPrecisions[column - 1];
}
public int getScale(int column) {
return mScales[column - 1];
}
public String getTableName(int column) {
return mTableNames[column - 1];
}
public String getCatalogName(int column) {
return mCatalogNames[column - 1];
}
public int getColumnType(int column) {
return mTypes[column - 1];
}
public String getColumnTypeName(int column) {
return mTypeNames[column - 1];
}
public String getColumnClassName(int column) {
return mClassNames[column - 1];
}
public <T> T unwrap(Class<T> iface) throws SQLException {
throw new SQLException("unsupported");
}
public boolean isWrapperFor(Class<?> iface) {
return false;
}
}