jdbcschema.java
来自「数据仓库展示程序」· Java 代码 · 共 1,385 行 · 第 1/3 页
JAVA
1,385 行
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/aggmatcher/JdbcSchema.java#7 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// Copyright (C) 2005-2005 Julian Hyde and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.rolap.aggmatcher;
import mondrian.olap.MondrianDef;
import mondrian.resource.MondrianResource;
import mondrian.rolap.RolapAggregator;
import mondrian.rolap.RolapStar;
import mondrian.resource.MondrianResource;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.*;
import java.util.*;
/**
* This class is used to scrap a database and store information about its
* tables and columns.
* A database has tables. A table has columns. A column has one or more usages.
* A usage might be a column being used as a foreign key or as part of a
* measure.
* <p>
* Tables are created when calling code requests the set of available
* tables. This call <code>getTables()</code> causes all tables to be loaded.
* But a table's columns are not loaded until, on a table-by-table basis,
* a request is made to get the set of columns associated with the table.
* Since, the AggTableManager first attempts table name matches (recognition)
* most tables do not match, so why load their columns.
* Of course, as a result, there are a host of methods that can throw an
* SQLException, rats.
*
* @author <a>Richard M. Emberson</a>
* @version $Id: //open/mondrian/src/main/mondrian/rolap/aggmatcher/JdbcSchema.java#7 $
*/
public class JdbcSchema {
private static final Logger LOGGER =
Logger.getLogger(JdbcSchema.class);
private static final MondrianResource mres = MondrianResource.instance();
/**
* Get the Logger.
*
* @return
*/
public Logger getLogger() {
return LOGGER;
}
public interface Factory {
JdbcSchema makeDB(DataSource dataSource);
void clearDB(DataSource dataSource);
}
public static class StdFactory implements Factory {
private final WeakHashMap dbMap = new WeakHashMap();
StdFactory() {
}
public JdbcSchema makeDB(DataSource dataSource) {
JdbcSchema db = (JdbcSchema) dbMap.get(dataSource);
if (db == null) {
db = new JdbcSchema(dataSource);
dbMap.put(dataSource, db);
}
return db;
}
public void clearDB(DataSource dataSource) {
JdbcSchema db = (JdbcSchema) dbMap.get(dataSource);
if (db != null) {
db.clear();
}
}
}
public static final String FACTORY_CLASS =
"mondrian.rolap.aggregates.jdbcFactoryClass";
private static Factory factory;
private static void makeFactory() {
if (factory == null) {
String classname = System.getProperty(FACTORY_CLASS);
if (classname == null) {
factory = new StdFactory();
} else {
try {
Class clz = Class.forName(classname);
factory = (Factory) clz.newInstance();
} catch (ClassNotFoundException ex) {
throw mres.BadJdbcFactoryClassName.ex(classname);
} catch (InstantiationException ex) {
throw mres.BadJdbcFactoryInstantiation.ex(classname);
} catch (IllegalAccessException ex) {
throw mres.BadJdbcFactoryAccess.ex(classname);
}
}
}
}
public static synchronized void clearDB(DataSource dataSource) {
makeFactory();
factory.clearDB(dataSource);
}
public static synchronized JdbcSchema makeDB(DataSource dataSource) {
makeFactory();
return factory.makeDB(dataSource);
}
//
// Types of column usages.
//
public static final int UNKNOWN_COLUMN_USAGE = 0x0001;
public static final int FOREIGN_KEY_COLUMN_USAGE = 0x0002;
public static final int MEASURE_COLUMN_USAGE = 0x0004;
public static final int LEVEL_COLUMN_USAGE = 0x0008;
public static final int FACT_COUNT_COLUMN_USAGE = 0x0010;
public static final int IGNORE_COLUMN_USAGE = 0x0020;
public static final String UNKNOWN_COLUMN_NAME = "UNKNOWN";
public static final String FOREIGN_KEY_COLUMN_NAME = "FOREIGN_KEY";
public static final String MEASURE_COLUMN_NAME = "MEASURE";
public static final String LEVEL_COLUMN_NAME = "LEVEL";
public static final String FACT_COUNT_COLUMN_NAME = "FACT_COUNT";
public static final String IGNORE_COLUMN_NAME = "IGNORE";
/**
* Determine if the parameter represents a single column type, i.e., the
* column only has one usage.
*
* @param columnType
* @return true if column has only one usage.
*/
public static boolean isUniqueColumnType(int columnType) {
switch (columnType) {
case UNKNOWN_COLUMN_USAGE :
return true;
case FOREIGN_KEY_COLUMN_USAGE :
return true;
case MEASURE_COLUMN_USAGE :
return true;
case LEVEL_COLUMN_USAGE :
return true;
case FACT_COUNT_COLUMN_USAGE :
return true;
case IGNORE_COLUMN_USAGE :
return true;
default :
return false;
}
}
/**
* Map from column type enum to column type name or list of names if the
* parameter represents more than on usage.
*
* @param columnType
* @return
*/
public static String convertColumnTypeToName(int columnType) {
switch (columnType) {
case UNKNOWN_COLUMN_USAGE :
return UNKNOWN_COLUMN_NAME;
case FOREIGN_KEY_COLUMN_USAGE :
return FOREIGN_KEY_COLUMN_NAME;
case MEASURE_COLUMN_USAGE :
return MEASURE_COLUMN_NAME;
case LEVEL_COLUMN_USAGE :
return LEVEL_COLUMN_NAME;
case FACT_COUNT_COLUMN_USAGE :
return FACT_COUNT_COLUMN_NAME;
case IGNORE_COLUMN_USAGE :
return IGNORE_COLUMN_NAME;
default :
// its a multi-purpose column
StringBuffer buf = new StringBuffer();
if ((columnType & UNKNOWN_COLUMN_USAGE) != 0) {
buf.append(UNKNOWN_COLUMN_NAME);
}
if ((columnType & FOREIGN_KEY_COLUMN_USAGE) != 0) {
if (buf.length() != 0) {
buf.append('|');
}
buf.append(FOREIGN_KEY_COLUMN_NAME);
}
if ((columnType & MEASURE_COLUMN_USAGE) != 0) {
if (buf.length() != 0) {
buf.append('|');
}
buf.append(MEASURE_COLUMN_NAME);
}
if ((columnType & LEVEL_COLUMN_USAGE) != 0) {
if (buf.length() != 0) {
buf.append('|');
}
buf.append(LEVEL_COLUMN_NAME);
}
if ((columnType & FACT_COUNT_COLUMN_USAGE) != 0) {
if (buf.length() != 0) {
buf.append('|');
}
buf.append(FACT_COUNT_COLUMN_NAME);
}
if ((columnType & IGNORE_COLUMN_USAGE) != 0) {
if (buf.length() != 0) {
buf.append('|');
}
buf.append(IGNORE_COLUMN_NAME);
}
return buf.toString();
}
}
/**
* Returns true if the parameter is a java.sql.Type numeric type.
*
* @param javaType
* @return
*/
public static boolean isNumeric(int javaType) {
switch (javaType) {
case Types.TINYINT :
case Types.SMALLINT :
case Types.INTEGER :
case Types.BIGINT :
case Types.FLOAT :
case Types.REAL :
case Types.DOUBLE :
case Types.NUMERIC :
case Types.DECIMAL :
return true;
default :
return false;
}
}
/**
* Returns true if the parameter is a java.sql.Type text type.
*
* @param javaType
* @return
*/
public static boolean isText(int javaType) {
switch (javaType) {
case Types.CHAR :
case Types.VARCHAR :
case Types.LONGVARCHAR :
return true;
default :
return false;
}
}
//
// Usages of tables.
//
public static final int UNKNOWN_TABLE_USAGE = 10;
public static final int FACT_TABLE_USAGE = 11;
public static final int AGG_TABLE_USAGE = 12;
public static final String UNKNOWN_TABLE_USAGE_NAME = "UNKNOWN";
public static final String FACT_TABLE_USAGE_NAME = "FACT";
public static final String AGG_TABLE_USAGE_NAME = "AGG";
/**
* Convert from table usage enum to table usage name.
*
* @param tableUsage
* @return
*/
public static String convertTableUsageToName(int tableUsage) {
switch (tableUsage) {
case UNKNOWN_TABLE_USAGE :
return UNKNOWN_TABLE_USAGE_NAME;
case FACT_TABLE_USAGE :
return FACT_TABLE_USAGE_NAME;
case AGG_TABLE_USAGE :
return AGG_TABLE_USAGE_NAME;
default :
return UNKNOWN_TABLE_USAGE_NAME;
}
}
//
// Types of tables.
//
public static final String UNKNOWN_TABLE_TYPE = "UNKNOWN";
public static final String TABLE_TABLE_TYPE = "TABLE";
public static final String VIEW_TYPE = "VIEW";
public static final String SYSTEM_TABLE_TABLE_TYPE = "SYSTEM TABLE";
public static final String GLOBAL_TEMP_TABLE_TYPE = "GLOBAL TEMPORARY";
public static final String LOCAL_TEMP_TABLE_TYPE = "LOCAL TEMPORARY";
public static final String ALIAS_TABLE_TYPE = "ALIAS";
public static final String SYNONYM_TABLE_TYPE = "SYNONYM";
/**
* A table in a database.
*/
public class Table {
/**
* A column in a table.
*/
public class Column {
/**
* A usage of a column.
*/
public class Usage {
private final int columnType;
private String symbolicName;
private RolapAggregator aggregator;
////////////////////////////////////////////////////
//
// These instance variables are used to hold
// stuff which is determines at one place and
// then used somewhere else. Generally, a usage
// is created before all of its "stuff" can be
// determined, hence, usage is not a set of classes,
// rather its one class with a bunch of instance
// variables which may or may not be used.
//
// measure stuff
public RolapStar.Measure rMeasure;
// hierarchy stuff
public MondrianDef.Relation relation;
public MondrianDef.Expression joinExp;
public String levelColumnName;
// level
public RolapStar.Column rColumn;
// for subtables
public RolapStar.Table rTable;
public String rightJoinConditionColumnName;
// It is used to hold the (possible null) prefix to
// use during aggregate table generation (See AggGen).
public String usagePrefix;
//
////////////////////////////////////////////////////
Usage(final int columnType) {
this.columnType = columnType;
}
/**
* This is the column with which this usage is associated.
*
* @return the usage's column.
*/
public Column getColumn() {
return JdbcSchema.Table.Column.this;
}
/**
* The column usage type.
*
* @return
*/
public int getColumnType() {
return columnType;
}
/**
* Is this usage of this type.
*
* @param columnType
* @return
*/
public boolean isColumnType(final int columnType) {
return ((this.columnType & columnType) != 0);
}
/**
* Set the symbolic (logical) name associated with this usage.
* For example, this might be the measure's name.
*
* @param symbolicName
*/
public void setSymbolicName(final String symbolicName) {
this.symbolicName = symbolicName;
}
/**
* Get usage's symbolic name.
*
* @return
*/
public String getSymbolicName() {
return symbolicName;
}
/**
* Set the aggregator associated with this usage (if its a
* measure usage).
*
* @param aggregator
*/
public void setAggregator(final RolapAggregator aggregator) {
this.aggregator = aggregator;
}
/**
* Get the aggregator associated with this usage (if its a
* measure usage, otherwise null).
*
* @return
*/
public RolapAggregator getAggregator() {
return aggregator;
}
public String toString() {
StringWriter sw = new StringWriter(64);
PrintWriter pw = new PrintWriter(sw);
print(pw, "");
pw.flush();
return sw.toString();
}
public void print(final PrintWriter pw, final String prefix) {
if (getSymbolicName() != null) {
pw.print("symbolicName=");
pw.print(getSymbolicName());
}
if (getAggregator() != null) {
pw.print(", aggregator=");
pw.print(getAggregator().getName());
}
pw.print(", columnType=");
pw.print(convertColumnTypeToName(getColumnType()));
}
}
/** This is the name of the column. */
private final String name;
/** This is the java.sql.Type enum of the column in the database. */
private int type;
/**
* This is the java.sql.Type name of the column in the database.
*/
private String typeName;
/** This is the size of the column in the database. */
private int columnSize;
/** The number of fractional digits. */
private int decimalDigits;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?