Skip to content

Commit fc332e3

Browse files
author
dlopez
committed
Initial version
1 parent 12fcb1e commit fc332e3

10 files changed

Lines changed: 465 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@
2121

2222
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2323
hs_err_pid*
24+
25+
.idea
26+
*.iml

pom.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>io.github.jdlopez</groupId>
8+
<artifactId>sqlcmd</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<dependencies>
12+
<dependency>
13+
<groupId>junit</groupId>
14+
<artifactId>junit</artifactId>
15+
<version>4.12</version>
16+
<scope>test</scope>
17+
</dependency>
18+
</dependencies>
19+
20+
<build>
21+
<plugins>
22+
<plugin>
23+
<groupId>org.apache.maven.plugins</groupId>
24+
<artifactId>maven-compiler-plugin</artifactId>
25+
<version>3.8.1</version>
26+
<configuration>
27+
<release>11</release>
28+
</configuration>
29+
</plugin>
30+
</plugins>
31+
</build>
32+
</project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package es.jdlopez.sqlcmd;
2+
3+
import java.beans.Introspector;
4+
import java.beans.PropertyDescriptor;
5+
import java.text.SimpleDateFormat;
6+
import java.util.Date;
7+
import java.util.Properties;
8+
9+
public class BeanReader {
10+
11+
private static SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
12+
13+
public static <T> T fromProperties(Properties properties, Class<T> clazz) throws ConfigException {
14+
try {
15+
T ret = clazz.getDeclaredConstructor().newInstance();
16+
for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors()) {
17+
propertyDescriptor.getWriteMethod().invoke(ret,
18+
convertValue(propertyDescriptor, properties.getProperty(propertyDescriptor.getName())));
19+
}
20+
return ret;
21+
} catch (ConfigException e) {
22+
throw e; // no need to cascade one more
23+
} catch (Exception e) {
24+
throw new ConfigException(null, e.getMessage(), e);
25+
}
26+
}
27+
28+
private static Object convertValue(PropertyDescriptor propertyDescriptor, String value) throws ConfigException {
29+
Class<?> clazz = propertyDescriptor.getWriteMethod().getParameterTypes()[0];
30+
//if (clazz.isAssignableFrom(String.class))
31+
// return value;
32+
//else
33+
try {
34+
if (value == null && !clazz.isPrimitive())
35+
return null;
36+
if (clazz.isAssignableFrom(Integer.class))
37+
return Integer.valueOf(value);
38+
else if (clazz.isAssignableFrom(Date.class))
39+
return df.parse(value);
40+
else if (clazz.isAssignableFrom(Boolean.class) || clazz.isAssignableFrom(boolean.class))
41+
return Boolean.valueOf(value);
42+
else
43+
return value;
44+
} catch (Exception e) {
45+
String name = "unknown";
46+
if (propertyDescriptor != null)
47+
name = propertyDescriptor.getName();
48+
throw new ConfigException(name, e.getMessage(), e);
49+
}
50+
}
51+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package es.jdlopez.sqlcmd;
2+
3+
public class ConfigException extends Exception {
4+
private String fieldName;
5+
6+
public ConfigException(String fieldName, String message, Throwable cause) {
7+
super(message, cause);
8+
this.fieldName = fieldName;
9+
}
10+
11+
public ConfigException(String fieldName, String message) {
12+
super(message);
13+
this.fieldName = fieldName;
14+
}
15+
16+
public String getFieldName() {
17+
return fieldName;
18+
}
19+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package es.jdlopez.sqlcmd;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
import java.net.MalformedURLException;
5+
import java.net.URL;
6+
import java.net.URLClassLoader;
7+
import java.sql.Connection;
8+
import java.sql.Driver;
9+
import java.sql.DriverManager;
10+
import java.sql.DriverPropertyInfo;
11+
import java.sql.SQLException;
12+
import java.sql.SQLFeatureNotSupportedException;
13+
import java.util.Properties;
14+
import java.util.logging.Logger;
15+
16+
/**
17+
* Jdbc Dynamic Driver loads .jar file driver from path instead of classpath
18+
* @see <a href="https://stackoverflow.com/questions/14478870/dynamically-load-the-jdbc-driver#14479658">dynamically-load-the-jdbc-driver on stackoverflow</a>
19+
*/
20+
public class DynamicDriver implements Driver {
21+
private Driver driver;
22+
23+
public DynamicDriver(Driver d) {
24+
this.driver = d;
25+
}
26+
27+
/**
28+
* Gets connection using DriverManager.registerDriver
29+
*/
30+
public static Connection getConnection(String driverPath, String driverClass, String jdbcUrl, String jdbcUser, String jdbcPass) throws SQLException {
31+
Connection conn = null;
32+
Driver d = null;
33+
try {
34+
URL u = new URL("jar:file:" + driverPath + "!/");
35+
URLClassLoader ucl = new URLClassLoader(new URL[]{u}, DynamicDriver.class.getClassLoader());
36+
d = (Driver) Class.forName(driverClass, true, ucl).getConstructor().newInstance();
37+
DriverManager.registerDriver(new DynamicDriver(d));
38+
conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPass);
39+
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | MalformedURLException | NoSuchMethodException | InvocationTargetException e) {
40+
throw new SQLException(e.getMessage(), e);
41+
}
42+
return conn;
43+
44+
}
45+
46+
public boolean acceptsURL(String u) throws SQLException {
47+
return this.driver.acceptsURL(u);
48+
}
49+
50+
public Connection connect(String u, Properties p) throws SQLException {
51+
return this.driver.connect(u, p);
52+
}
53+
54+
public int getMajorVersion() {
55+
return this.driver.getMajorVersion();
56+
}
57+
58+
public int getMinorVersion() {
59+
return this.driver.getMinorVersion();
60+
}
61+
62+
public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) throws SQLException {
63+
return this.driver.getPropertyInfo(u, p);
64+
}
65+
66+
public boolean jdbcCompliant() {
67+
return this.driver.jdbcCompliant();
68+
}
69+
70+
@Override
71+
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
72+
return null;
73+
}
74+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package es.jdlopez.sqlcmd;
2+
3+
import java.io.BufferedReader;
4+
import java.io.File;
5+
import java.io.FileInputStream;
6+
import java.io.FileReader;
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.io.InputStreamReader;
10+
import java.io.PrintWriter;
11+
import java.sql.Connection;
12+
import java.sql.ResultSet;
13+
import java.sql.ResultSetMetaData;
14+
import java.sql.SQLException;
15+
import java.sql.Statement;
16+
import java.util.Properties;
17+
18+
public class MainRunner {
19+
20+
public static void main (String[] args) throws Exception {
21+
RunnerConfig config = readArgs(args);
22+
InputStream in;
23+
if (config.getInputSQL() == null) {
24+
in = System.in;
25+
} else {
26+
File fIn = new File(config.getInputSQL());
27+
if (!fIn.exists())
28+
throw new ConfigException("InputSQL", config.getInputSQL() + " does not exists");
29+
in = new FileInputStream(fIn);
30+
}
31+
String sql = readAll(in);
32+
PrintWriter out = null;
33+
if (config.getOutputResult() == null)
34+
out = new PrintWriter(System.out);
35+
else
36+
out = new PrintWriter(config.getOutputResult());
37+
38+
Connection conn = null;
39+
try {
40+
conn = DynamicDriver.getConnection(config.getJdbcDriverPath(), config.getJdbcDriverClass(),
41+
config.getJdbcUrl(), config.getJdbcUser(), config.getJdbcPass());
42+
Statement st = conn.createStatement();
43+
boolean isResultSet = st.execute(sql);
44+
boolean hasMore = true;
45+
while (hasMore) {
46+
if (isResultSet)
47+
writeResultSet(st.getResultSet(), out, config);
48+
else
49+
out.println("UpdateCount = " + st.getUpdateCount());
50+
hasMore = st.getMoreResults();
51+
}
52+
53+
} finally {
54+
if (conn != null)
55+
conn.close();
56+
}
57+
}
58+
59+
private static void writeResultSet(ResultSet resultSet, PrintWriter out, RunnerConfig conf) throws SQLException {
60+
ResultSetMetaData rsmd = resultSet.getMetaData();
61+
int colCount = rsmd.getColumnCount();
62+
if (conf.getPrintHeader()) {
63+
for (int i = 1; i <= colCount; i++) {
64+
out.print(rsmd.getColumnName(i));
65+
if (i <= colCount)
66+
out.print(conf.getPrintFieldSeparator());
67+
}
68+
out.println();
69+
} // header
70+
while (resultSet.next()) {
71+
for (int i = 1; i <= colCount; i++) {
72+
out.print(resultSet.getString(i));
73+
if (i <= colCount)
74+
out.print(conf.getPrintFieldSeparator());
75+
} // for col
76+
out.println();
77+
} // while row
78+
}
79+
80+
private static String readAll(InputStream in) throws IOException {
81+
BufferedReader br = new BufferedReader(new InputStreamReader(in));
82+
StringBuffer sb = new StringBuffer();
83+
String line;
84+
while ((line = br.readLine()) != null)
85+
sb.append(line);
86+
br.close();
87+
return sb.toString();
88+
}
89+
90+
private static RunnerConfig readArgs(String[] args) throws ConfigException {
91+
RunnerConfig conf = null;
92+
if (args != null)
93+
for (String a: args) {
94+
if (a.startsWith("-c:")) { // config
95+
Properties p = new Properties();
96+
try {
97+
p.load(new FileReader(a.substring("-c:".length())));
98+
} catch (IOException e) {
99+
throw new ConfigException("configFile", "Reading config file", e);
100+
}
101+
conf = BeanReader.fromProperties(p, RunnerConfig.class);
102+
} // else if ... for any other args TODO
103+
}
104+
else
105+
throw new ConfigException(null, "No arguments");
106+
return conf;
107+
}
108+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package es.jdlopez.sqlcmd;
2+
3+
public class RunnerConfig {
4+
private String inputSQL;
5+
private String jdbcDriverPath;
6+
private String jdbcDriverClass;
7+
private String jdbcUrl;
8+
private String jdbcUser;
9+
private String jdbcPass;
10+
private String outputResult;
11+
private boolean printHeader;
12+
private String printFieldSeparator;
13+
14+
public String getInputSQL() {
15+
return inputSQL;
16+
}
17+
18+
public void setInputSQL(String inputSQL) {
19+
this.inputSQL = inputSQL;
20+
}
21+
22+
public String getJdbcDriverPath() {
23+
return jdbcDriverPath;
24+
}
25+
26+
public void setJdbcDriverPath(String jdbcDriverPath) {
27+
this.jdbcDriverPath = jdbcDriverPath;
28+
}
29+
30+
public String getJdbcDriverClass() {
31+
return jdbcDriverClass;
32+
}
33+
34+
public void setJdbcDriverClass(String jdbcDriverClass) {
35+
this.jdbcDriverClass = jdbcDriverClass;
36+
}
37+
38+
public String getJdbcUrl() {
39+
return jdbcUrl;
40+
}
41+
42+
public void setJdbcUrl(String jdbcUrl) {
43+
this.jdbcUrl = jdbcUrl;
44+
}
45+
46+
public String getJdbcUser() {
47+
return jdbcUser;
48+
}
49+
50+
public void setJdbcUser(String jdbcUser) {
51+
this.jdbcUser = jdbcUser;
52+
}
53+
54+
public String getJdbcPass() {
55+
return jdbcPass;
56+
}
57+
58+
public void setJdbcPass(String jdbcPass) {
59+
this.jdbcPass = jdbcPass;
60+
}
61+
62+
public String getOutputResult() {
63+
return outputResult;
64+
}
65+
66+
public void setOutputResult(String outputResult) {
67+
this.outputResult = outputResult;
68+
}
69+
70+
public boolean getPrintHeader() {
71+
return printHeader;
72+
}
73+
74+
public void setPrintHeader(boolean printHeader) {
75+
this.printHeader = printHeader;
76+
}
77+
78+
public String getPrintFieldSeparator() {
79+
return printFieldSeparator;
80+
}
81+
82+
public void setPrintFieldSeparator(String printFieldSeparator) {
83+
this.printFieldSeparator = printFieldSeparator;
84+
}
85+
}

0 commit comments

Comments
 (0)