package org.reldb.rel.v0.storage.relvars.external.jdbc;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import org.reldb.rel.exceptions.ExceptionFatal;
import org.reldb.rel.exceptions.ExceptionSemantic;
import org.reldb.rel.v0.generator.Generator;
import org.reldb.rel.v0.generator.SelectAttributes;
import org.reldb.rel.v0.interpreter.ClassPathHack;
import org.reldb.rel.v0.storage.RelDatabase;
import org.reldb.rel.v0.storage.relvars.RelvarCustomMetadata;
import org.reldb.rel.v0.storage.relvars.RelvarExternal;
import org.reldb.rel.v0.storage.relvars.RelvarGlobal;
import org.reldb.rel.v0.storage.relvars.RelvarHeading;
import org.reldb.rel.v0.storage.relvars.external.CSVLineParse;
import org.reldb.rel.v0.storage.relvars.external.ColumnName;
import org.reldb.rel.v0.storage.tables.TableExternal.DuplicateHandling;
import org.reldb.rel.v0.types.Heading;
import org.reldb.rel.v0.types.builtin.TypeCharacter;
import org.reldb.rel.v0.types.builtin.TypeInteger;
public class RelvarJDBCMetadata extends RelvarCustomMetadata {
public static final long serialVersionUID = 0;
private String connectionString;
private String address; // "jdbc:postgresql://localhost/database"
private String user; // "sqluser"
private String password; // "sqluserpw"
private String table; // "FEEDBACK.RELVAR"
// var myvar external jdbc
// "jdbc:postgresql://localhost/database,sqluser,sqluserpw,FEEDBACK.RELVAR";
private DuplicateHandling duplicates;
private static boolean driversLoaded = false;
public static void loadDrivers(RelDatabase database) {
if (driversLoaded)
return;
if (!ClassPathHack.isInOSGI()) {
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader newClassLoader;
try {
newClassLoader = new JDBCDriverLoader(database.getExtensionDirectory());
Thread.currentThread().setContextClassLoader(newClassLoader);
} catch (MalformedURLException e) {
throw new ExceptionFatal("RS0471: Malforumed URL in RelvarJDBCMetadata.loadDrivers(): " + e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
driversLoaded = true;
}
private static String obtainDriverList() {
String list = "";
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
if (!list.isEmpty())
list += ", ";
list += driver.getClass().getName();
}
return (list.isEmpty()) ? "<none>" : list;
}
public static RelvarHeading getHeading(RelDatabase database, String spec, DuplicateHandling duplicates) {
String[] values = CSVLineParse.parseTrimmed(spec);
if (values.length != 4)
throw new ExceptionSemantic("EX0014: Invalid arguments. Expected: URL, USER, PASSWORD, DATABASE.TABLE but got " + spec);
String address = values[0];
String user = values[1];
String password = values[2];
String table = values[3];
try {
loadDrivers(database);
Connection connect = DriverManager.getConnection(address, user, password);
Statement statement = connect.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table);
Heading heading = new Heading();
if (duplicates == DuplicateHandling.DUP_COUNT)
heading.add("_DUP_COUNT", TypeInteger.getInstance());
else if (duplicates == DuplicateHandling.AUTOKEY)
heading.add("_AUTOKEY", TypeInteger.getInstance());
for (int column = 1; column <= resultSet.getMetaData().getColumnCount(); column++)
heading.add(ColumnName.cleanName(resultSet.getMetaData().getColumnName(column)), TypeCharacter.getInstance());
RelvarHeading relvarHeading = new RelvarHeading(heading);
if (duplicates == DuplicateHandling.AUTOKEY) {
SelectAttributes keyAttribute = new SelectAttributes();
keyAttribute.add("_AUTOKEY");
relvarHeading.addKey(keyAttribute);
}
return relvarHeading;
} catch (SQLException e) {
throw new ExceptionSemantic("EX0016: " + e.toString() + ". Drivers available: " + obtainDriverList());
}
}
@Override
public String getSourceDefinition() {
return "EXTERNAL JDBC \"" + address + "," + user + "," + password + "," + table + "\" " + duplicates;
}
public RelvarJDBCMetadata(RelDatabase database, String owner, String spec, DuplicateHandling duplicates) {
super(database, getHeading(database, spec, duplicates), owner);
String[] values = CSVLineParse.parseTrimmed(spec);
address = values[0];
user = values[1];
password = values[2];
table = values[3];
this.duplicates = duplicates;
connectionString = spec;
}
@Override
public RelvarGlobal getRelvar(String name, RelDatabase database) {
try {
loadDrivers(database);
Connection connect = DriverManager.getConnection(address, user, password);
Statement statement = connect.createStatement();
statement.executeQuery("select * from " + table);
} catch (SQLException e) {
throw new ExceptionSemantic("EX0019: Table " + table + " no longer exists.");
}
return new RelvarExternal(name, database, new Generator(database, System.out), this, duplicates);
}
@Override
public void dropRelvar(RelDatabase database) {
}
public String getConnectionString() {
return connectionString;
}
public String getPath() {
return address;
}
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public String getTable() {
return table;
}
@Override
public String tableClassName() {
return "TableJDBC";
}
@Override
public String getType() {
return "JDBC";
}
}