package com.linkedin.databus.util;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* 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.
*
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* This class has been replaced by TypeInfoFactoryInteractive
*/
@Deprecated
public class TypeInfoFactory
{
public TypeInfo getTypeInfo(Connection con, String typeOwner, String typeName, int precision, int scale,String primaryKey)
throws SQLException
{
if(isSimpleType(con, typeOwner, typeName))
{
return buildSimpleTypeInfo(con, typeOwner, typeName, precision, scale);
}
else if(isTableType(con, typeOwner, typeName))
{
return buildTableType(con, typeOwner, typeName,primaryKey);
}
else if(isCollectionType(con, typeOwner, typeName))
{
return buildCollectionTypeInfo(con, typeOwner, typeName);
}
else if(isUserType(con, typeOwner, typeName))
{
return buildUserTypeInfo(con, typeOwner, typeName);
}
else
{
throw new SQLException("Cannot determine type info for the attribute (" + typeOwner + "." + typeName + ").");
}
}
// Table / View Types
public boolean isTableType(Connection con, String tableOwner, String tableName)
{
PreparedStatement stmt = null;
try
{
String fullTableName = tableOwner + "." + tableName;
stmt = con.prepareStatement("SELECT * FROM " + fullTableName + " WHERE 0=1") ;
stmt.executeQuery();
return true;
}
catch(SQLException ex)
{
return false;
}
finally
{
SchemaUtils.close(stmt);
}
}
public TableTypeInfo buildTableType(Connection con, String tableOwner, String tableName,String pk)
throws SQLException
{
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
String fullTableName = tableOwner + "." + tableName;
stmt = con.prepareStatement("SELECT * FROM " + fullTableName + " WHERE 0=1");
rs = stmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
List<FieldInfo> fields = new ArrayList<FieldInfo>();
int numColumns = rsmd.getColumnCount();
for(int column=1; column <= numColumns; column++)
{
String columnName = rsmd.getColumnName(column);
System.out.println("Processing column " + tableName + "." + columnName + ":" + rsmd.getColumnTypeName(column));
int columnPrecision = rsmd.getPrecision(column);
int columnScale = rsmd.getScale(column);
String columnTypeName;
String columnTypeOwner;
String[] columnTypeParts = rsmd.getColumnTypeName(column).split("\\.");
if(columnTypeParts.length == 1)
{
columnTypeOwner = null;
columnTypeName = columnTypeParts[0];
}
else
{
columnTypeOwner = columnTypeParts[0];
columnTypeName = columnTypeParts[1];
}
if (columnTypeName.endsWith(" UNSIGNED")) {
columnTypeName = columnTypeName.substring(0, columnTypeName.length() - " UNSIGNED".length());
}
TypeInfo typeInfo = getTypeInfo(con, columnTypeOwner, columnTypeName, columnPrecision, columnScale,"");
FieldInfo field = new FieldInfo(columnName, typeInfo, column - 1);
fields.add(field);
}
return new TableTypeInfo(tableOwner, tableName, fields,pk);
}
finally
{
SchemaUtils.close(rs);
SchemaUtils.close(stmt);
}
}
// User Types
public boolean isUserType(Connection con, String ownerName, String typeName)
throws SQLException
{
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
// Query to see if user attribute information exists for this user type
stmt = con.prepareStatement("SELECT 1 FROM ALL_TYPE_ATTRS " +
"WHERE OWNER=? AND TYPE_NAME=? AND ROWNUM < 2");
stmt.setString(1, ownerName);
stmt.setString(2, typeName);
rs = stmt.executeQuery();
// If a row exists then this is a user type
return rs.next();
}
finally
{
SchemaUtils.close(rs);
SchemaUtils.close(stmt);
}
}
public UserTypeInfo buildUserTypeInfo(Connection con, String typeOwner, String typeName)
throws SQLException
{
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
// Query to select the user type information
stmt = con.prepareStatement("SELECT ATTR_NAME, ATTR_TYPE_OWNER, ATTR_TYPE_NAME, PRECISION, SCALE FROM ALL_TYPE_ATTRS " +
"WHERE OWNER=? AND TYPE_NAME=?" +
"ORDER BY ATTR_NO");
stmt.setString(1, typeOwner);
stmt.setString(2, typeName);
rs = stmt.executeQuery();
// If there was no row then this is not a user type
if(!rs.next())
{
throw new SQLException("Not a user type. (" + typeName + ")");
}
// Build up the list of attributes (fields) in this user type
List<FieldInfo> fields = new ArrayList<FieldInfo>();
do
{
String attrName = rs.getString(1);
String attrTypeOwner = rs.getString(2);
String attrTypeName = rs.getString(3);
int attrPrecision = rs.getInt(4);
int attrScale = rs.getInt(5);
TypeInfo typeInfo = getTypeInfo(con, attrTypeOwner, attrTypeName, attrPrecision, attrScale,"");
fields.add(new FieldInfo(attrName, typeInfo, fields.size()));
} while(rs.next());
return new UserTypeInfo(typeOwner, typeName, fields);
}
finally
{
SchemaUtils.close(rs);
SchemaUtils.close(stmt);
}
}
// Built in types
public boolean isSimpleType(Connection con, String typeOwner, String typeName)
throws SQLException
{
//For whatever reason, the JDBC driver does not return this as primitive type
if (typeName.equalsIgnoreCase("NVARCHAR")
|| typeName.equalsIgnoreCase("NVARCHAR2")
|| typeName.contains("XML"))
return true;
ResultSet rs = null;
try
{
// This returns a ResultSet with all the built in types like NUMBER, VARCHAR2, CLOB, etc.
rs = con.getMetaData().getTypeInfo();
while(rs.next())
{
//System.out.print(" " + rs.getString("TYPE_NAME") + " ");
if(rs.getString("TYPE_NAME").equalsIgnoreCase(typeName))
return true;
}
return false;
}
finally
{
SchemaUtils.close(rs);
}
}
public SimpleTypeInfo buildSimpleTypeInfo(Connection con, String typeOwner, String typeName, int precision, int scale)
throws SQLException
{
if(!isSimpleType(con, typeOwner, typeName))
{
throw new SQLException("Not a simple type. (" + typeName + ")");
}
return new SimpleTypeInfo(typeName, precision, scale);
}
// Collections
public boolean isCollectionType(Connection con, String ownerName, String typeName)
throws SQLException
{
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
// Query to see if collection type information exists for this collection type
stmt = con.prepareStatement("SELECT 1 FROM ALL_COLL_TYPES " +
"WHERE OWNER=? AND TYPE_NAME=? AND ROWNUM < 2");
stmt.setString(1, ownerName);
stmt.setString(2, typeName);
rs = stmt.executeQuery();
// If collection information exists then it is a collection type
return rs.next();
}
finally
{
SchemaUtils.close(rs);
SchemaUtils.close(stmt);
}
}
public CollectionTypeInfo buildCollectionTypeInfo(Connection con, String ownerName, String typeName)
throws SQLException
{
PreparedStatement stmt = null;
ResultSet rs = null;
try
{
// Query to select the collection type information
stmt = con.prepareStatement("SELECT ELEM_TYPE_OWNER, ELEM_TYPE_NAME, PRECISION, SCALE FROM ALL_COLL_TYPES " +
"WHERE OWNER=? AND TYPE_NAME=?");
stmt.setString(1, ownerName);
stmt.setString(2, typeName);
rs = stmt.executeQuery();
// If there was no row then this is not a collection type
if(!rs.next())
{
throw new SQLException("Not a collection type. (" + typeName + ")");
}
// Get the columns
String elementTypeOwner = rs.getString(1);
String elementTypeName = rs.getString(2);
int precision = rs.getInt(3);
int scale = rs.getInt(4);
// Build the type for the element type ("this is a collection of ...")
TypeInfo elementTypeInfo = getTypeInfo(con, elementTypeOwner, elementTypeName, precision, scale,"");
// Construct and return the new CollectionTypeInfo
return new CollectionTypeInfo(ownerName, typeName, elementTypeInfo);
}
finally
{
SchemaUtils.close(rs);
SchemaUtils.close(stmt);
}
}
}