blob: 8ab8453a87ab1e607546d119706750767ef2841a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.empire.dbms.oracle;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.empire.data.DataType;
import org.apache.empire.db.DBColumn;
import org.apache.empire.db.DBTable;
import org.apache.empire.db.DBView;
public class OracleDataDictionnary {
/**
* Immutable column info helper class
*/
public class ColumnInfo {
private final String dataType;
private final int charLength;
private final int dataLength;
private final int dataPrecision;
private final int dataScale;
private final String nullable;
public ColumnInfo(String dataType, int charLength, int dataLength, int dataPrecision, int dataScale, String nullable)
{
super();
this.dataType = dataType;
this.charLength = charLength;
this.dataLength = dataLength;
this.dataPrecision = dataPrecision;
this.dataScale = dataScale;
this.nullable = nullable;
}
public int getCharLength()
{
return charLength;
}
public int getDataLength()
{
return dataLength;
}
public int getDataPrecision()
{
return dataPrecision;
}
public int getDataScale()
{
return dataScale;
}
public String getDataType()
{
return dataType;
}
public String getNullable()
{
return nullable;
}
}
protected static final Logger log = LoggerFactory.getLogger(OracleDataDictionnary.class);
private final HashMap<String, HashMap<String, ColumnInfo>> dictionnary = new HashMap<String, HashMap<String, ColumnInfo>>();
private Map<String, DataType[]> dataTypeMapping = null;
/**
* Defines mapping of the Empire-db data types with the oracle data types.
*/
public OracleDataDictionnary() {
dataTypeMapping = new HashMap<String, DataType[]>();
dataTypeMapping.put("VARCHAR2", new DataType[] { DataType.VARCHAR });
dataTypeMapping.put("CHAR", new DataType[] { DataType.CHAR, DataType.BOOL });
dataTypeMapping.put("NUMBER", new DataType[] { DataType.DECIMAL, DataType.FLOAT,
DataType.INTEGER, DataType.AUTOINC, DataType.BOOL });
dataTypeMapping.put("DATE", new DataType[] { DataType.DATE, DataType.DATETIME });
dataTypeMapping.put("TIMESTAMP",new DataType[] { DataType.TIMESTAMP });
dataTypeMapping.put("CLOB", new DataType[] { DataType.CLOB });
dataTypeMapping.put("BLOB", new DataType[] { DataType.BLOB });
}
public HashMap<String, HashMap<String, ColumnInfo>> getDictionnary() {
return dictionnary;
}
public void fillDataDictionnary(String tableName, String columnName, String dataType, int charLength, int dataLength, int dataPrecision, int dataScale, String nullable) {
ColumnInfo colInfo = new ColumnInfo(dataType, charLength, dataLength, dataPrecision, dataScale, nullable);
HashMap<String, ColumnInfo> columns = new HashMap<String, ColumnInfo>();
if(dictionnary.containsKey(tableName)) {
columns = dictionnary.get(tableName);
}
columns.put(columnName, colInfo);
dictionnary.put(tableName, columns);
}
/**
* Checks if the ORACLE datatype can be mapped with a DBTable data type.
*
* @param dbDatatype ORACLE datatype
* @param colDataType DBTableColumn datatype
* @return true if the type can be mapped, false otherwise
*/
private boolean checkMapping(String dbDatatype, DataType colDataType)
{
DataType[] colTypes = dataTypeMapping.get(dbDatatype);
if(colTypes == null)
{
log.warn("MAPPING NOT DEFINED FOR " + dbDatatype + " -> " + colDataType);
return false;
}
for (int i = 0; i < colTypes.length; i++)
{
if (colTypes[i] == colDataType)
return true;
}
return false;
}
/*
* Checks a DBTableColumn definition. The set attributes must fint to the overgiven db attributes.
*
* @param col Column to check
* @param dbDataType Datatype of db column
* @param dbDataLength Datalength of db column
* @param dbDataPrecision Data precision of db column
* @param dbDataScale Data scale of db column
* @param dbRequired Is nullable of the db column
* @return true if the column definition fits, false otherwise
private boolean checkColumnDefinition(DBColumn col, String dbDataType, int dbDataLength, int dbDataPrecision,
int dbDataScale, boolean dbRequired)
{
// FUTURE find a way to check the precision for numbers
boolean result = true;
DataType colDataType = col.getDataType();
int size = (int) col.getSize();
// check if the column data type can be mapped with the db column data type
if (checkMapping(dbDataType, colDataType) == false)
{
log.warn("WRONG DATATYPE \t\t\t\t\t\t: [" + col.getRowSet().getName() + "][" + col.getName() + "] -> DB : ["
+ dbDataType + "]" + "[" + dbDataLength + "]");
result = false;
}
// check if the column is required and if the column is defined as required
if (dbRequired && col.isRequired() == false)
{
log.warn("COLUMN IS REQUIRED \t\t\t\t\t: [" + col.getRowSet().getName() + "][" + col.getName() + "]");
result = false;
}
else if (dbRequired == false && col.isRequired() == true)
{
log.warn("COLUMN IS NOT REQUIRED \t\t\t\t: [" + col.getRowSet().getName() + "][" + col.getName() + "]");
result = false;
}
// check the data length if the column is a varchar2
if (dbDataType.equals("VARCHAR2") && (dbDataLength != size))
{
log.warn("WRONG COLUMN SIZE \t\t\t\t\t: [" + col.getRowSet().getName() + "][" + col.getName() + "] -> DB : ["
+ dbDataType + "][" + dbDataLength + "]");
result = false;
}
return result;
}
*/
private void checkColumn(DBColumn column, ColumnInfo colInfo)
{
if(checkMapping(colInfo.getDataType(), column.getDataType()) == false) {
log.warn("WRONG DATA TYPE: \t" + column.getFullName() + " is set to " + column.getDataType() +
" instead of " + colInfo.getDataType());
}
if(colInfo.getDataType().equals("VARCHAR2") && (column.getSize() != colInfo.getCharLength())) {
log.warn("WRONG COLUMN SIZE: \t" + column.getFullName() + " is set to " + (int)column.getSize() +
" instead of " + colInfo.getCharLength());
}
if(column.isRequired() != colInfo.getNullable().equals("N")) {
log.warn("WRONG NULLABLE FLAG: \t" + column.getFullName() + " is set to " + column.isRequired() +
" instead of " + colInfo.getNullable().equals("N"));
}
}
public void checkDBTableDefinition(List<DBTable> dbTables) {
// go through all tables defined in the Java code
for(DBTable currentTable: dbTables) {
String dbTableName = currentTable.getName();
// check if the table name is in the data dictionnary
if(this.dictionnary.containsKey(dbTableName)) {
// go through all columns of the table
for(DBColumn currentColumn : currentTable.getColumns()) {
Collection<String> dictColumns = this.dictionnary.get(dbTableName).keySet();
// check if the column name is in the data dictionnary
if(dictColumns.contains(currentColumn.getName())) {
// go through all columns of the table in the data dictionnary
for(String dictColumn : dictColumns) {
// compare the columnnames
if(currentColumn.getName().equals(dictColumn)) {
ColumnInfo colInfo = this.dictionnary.get(currentTable.getName()).get(dictColumn);
checkColumn(currentColumn, colInfo);
}
}
}
else {
log.warn("MISSING COLUMN: \t" + currentColumn.getFullName() + " does not exist in database");
}
}
}
else {
log.warn("MISSING TABLE: \t" + currentTable.getName() + " does not exist in database");
}
}
}
public void checkDBViewDefinition(List<DBView> dbViews) {
// go through all views defined in the Java code
for(DBView currentView: dbViews) {
String dbviewName = currentView.getName();
// check if the view name is in the data dictionnary
if(this.dictionnary.containsKey(dbviewName)) {
// go through all columns of the table
for(DBColumn currentColumn : currentView.getColumns()) {
Collection<String> dictColumns = this.dictionnary.get(dbviewName).keySet();
// check if the column name is in the data dictionnary
if(dictColumns.contains(currentColumn.getName())) {
// go through all columns of the view in the data dictionnary
for(String dictColumn : dictColumns) {
// compare the columnnames
if(currentColumn.getName().equals(dictColumn)) {
ColumnInfo colInfo = this.dictionnary.get(currentView.getName()).get(dictColumn);
if(checkMapping(colInfo.getDataType(), currentColumn.getDataType()) == false) {
log.warn("WRONG DATA TYPE: \t" + currentColumn.getFullName() + " is set to " + currentColumn.getDataType() +
" instead of " + colInfo.getDataType());
}
}
}
}
else {
log.warn("MISSING COLUMN: \t" + currentColumn.getFullName() + " does not exist in database.");
}
}
}
else {
log.warn("MISSING VIEW: \t" + currentView.getName() + " does not exist in database.");
}
}
}
}