From b1786c4340685b78d1c8febe8daa4a13e9bbc30d Mon Sep 17 00:00:00 2001 From: jdlopez Date: Tue, 15 Mar 2022 19:28:56 +0100 Subject: [PATCH] Added results sendmail on success. Some header decorations. Better handling of multiple-results --- README.md | 27 +++++- pom.xml | 19 ++++- .../java/es/jdlopez/sqlcmd/MainRunner.java | 67 +++++++++++++-- .../java/es/jdlopez/sqlcmd/RunnerConfig.java | 82 +++++++++++++++++++ src/main/java/es/jdlopez/sqlcmd/SendMail.java | 59 +++++++++++++ src/test/java/es/jdlopez/sqlcmd/TestMain.java | 24 ++++++ src/test/resources/sample.properties | 15 +++- src/test/resources/test1.sql | 15 ++++ 8 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 src/main/java/es/jdlopez/sqlcmd/SendMail.java create mode 100644 src/test/java/es/jdlopez/sqlcmd/TestMain.java create mode 100644 src/test/resources/test1.sql diff --git a/README.md b/README.md index 16c4fbd..3809879 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # sqlcmd -SQL command line executor using JDBC drivers. Useful for cron jobs and some automation. Porting of my previous sf.net code +SQL command line executor using JDBC drivers. Useful for cron jobs and some automation. + +_Porting of my previous sf.net code_ Usage: @@ -8,10 +10,10 @@ Usage: FROM MY_TABLE EOF -Config values: +## Config values: -* jdbcDriverPath=Path to jdbc driver jar (loaded dynamically) -* jdbcDriverClass=Jdbc Driver class full name +* jdbcDriverPath=Path to jdbc driver jar (loaded dynamically) if null it must be in classpath +* jdbcDriverClass=Jdbc Driver class full name (no need if driver registers itself) * jdbcUrl=Jdbc connection URL * jdbcUser= * jdbcPass= @@ -20,6 +22,23 @@ Config values: * printHeader=true/false If true adds header with query's column name. Default true * printFieldSeparator=Field separator for printing. Default tab (\t) +## Mail config values: + +Mail Server: +* mailHost=SMTP host +* mailPort=SMTP port +* mailAuth=true/false smtp server needs authentication? +* mailTLS=true/false smtp server needs TLS connection? +* mailUser=smtp auth username +* mailPass=smtp auth password +* +Mail message: +* mailFrom=Email addess in from field +* mailSubject=Subject field +* mailSendTo=Email addess in TO field + +## Config notes + Config values can be set also with parameters: -p:paran_name=param_value diff --git a/pom.xml b/pom.xml index 53c6b76..729ff4e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,15 +6,32 @@ io.github.jdlopez sqlcmd - 1.0-SNAPSHOT + 1.1 + + com.sun.mail + javax.mail + 1.6.2 + junit junit 4.12 test + + org.hsqldb + hsqldb + 2.3.2 + test + + + com.microsoft.sqlserver + mssql-jdbc + 7.4.1.jre8 + test + diff --git a/src/main/java/es/jdlopez/sqlcmd/MainRunner.java b/src/main/java/es/jdlopez/sqlcmd/MainRunner.java index 1b48ab5..5041921 100644 --- a/src/main/java/es/jdlopez/sqlcmd/MainRunner.java +++ b/src/main/java/es/jdlopez/sqlcmd/MainRunner.java @@ -8,7 +8,10 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.io.StringWriter; import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; @@ -30,24 +33,55 @@ public static void main (String[] args) throws Exception { } String sql = readAll(in); PrintWriter out = null; - if (config.getOutputResult() == null) - out = new PrintWriter(System.out); + StringWriter mailBody = null; + if (config.getMailSendTo() != null) { + mailBody = new StringWriter(); + out = new PrintWriter(mailBody); + } + else if (config.getOutputResult() == null) + out = new PrintWriter(System.out, true); else out = new PrintWriter(config.getOutputResult()); Connection conn = null; try { - conn = DynamicDriver.getConnection(config.getJdbcDriverPath(), config.getJdbcDriverClass(), + if (config.getJdbcDriverPath() == null) { + // driver in classpath and registered + conn = DriverManager.getConnection(config.getJdbcUrl(), config.getJdbcUser(), config.getJdbcPass()); + } else + conn = DynamicDriver.getConnection(config.getJdbcDriverPath(), config.getJdbcDriverClass(), config.getJdbcUrl(), config.getJdbcUser(), config.getJdbcPass()); Statement st = conn.createStatement(); boolean isResultSet = st.execute(sql); boolean hasMore = true; + int updateCount = st.getUpdateCount(); // just once per result while (hasMore) { - if (isResultSet) + if (isResultSet && updateCount < 0) writeResultSet(st.getResultSet(), out, config); else - out.println("UpdateCount = " + st.getUpdateCount()); - hasMore = st.getMoreResults(); + writeUpdateCount(updateCount, out, config); + isResultSet = st.getMoreResults(); + updateCount = st.getUpdateCount(); + hasMore = isResultSet || updateCount > -1; + } + // send result to mail? + if (config.getMailSendTo() != null && mailBody != null) { + SendMail sendMail; + if (config.getMailAuth() != null) { + sendMail = new SendMail(config.getMailHost(), + config.getMailPort(), + config.getMailFrom(), + Boolean.valueOf(config.getMailAuth()), + Boolean.valueOf(config.getMailTLS()), + config.getMailUser(), + config.getMailPass() + ); + } else { + sendMail = new SendMail(config.getMailHost(), + config.getMailPort(), + config.getMailFrom()); + } + sendMail.sendText(config.getMailSubject(), mailBody.toString(), config.getMailSendTo()); } } finally { @@ -56,16 +90,31 @@ public static void main (String[] args) throws Exception { } } + private static void writeUpdateCount(int updateCount, PrintWriter out, RunnerConfig config) { + String s; + if (config.getPrintHeader()) + s = String.format("==================\nUpdateCount = %d\n==================", updateCount); + else + s = "UpdateCount = " + updateCount; + out.println(s); + + } + private static void writeResultSet(ResultSet resultSet, PrintWriter out, RunnerConfig conf) throws SQLException { ResultSetMetaData rsmd = resultSet.getMetaData(); int colCount = rsmd.getColumnCount(); if (conf.getPrintHeader()) { + StringBuffer underline = new StringBuffer(); for (int i = 1; i <= colCount; i++) { out.print(rsmd.getColumnName(i)); - if (i < colCount) + underline.append(repeatChar('=', rsmd.getColumnName(i).length())); + if (i < colCount) { out.print(conf.getPrintFieldSeparator()); + underline.append(conf.getPrintFieldSeparator()); + } } out.println(); + out.println(underline.toString()); } // header while (resultSet.next()) { for (int i = 1; i <= colCount; i++) { @@ -78,6 +127,10 @@ private static void writeResultSet(ResultSet resultSet, PrintWriter out, RunnerC out.flush(); } + private static String repeatChar(char c, int length) { + return new String(new char[length]).replace('\0', c); + } + private static String readAll(InputStream in) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(in)); StringBuffer sb = new StringBuffer(); diff --git a/src/main/java/es/jdlopez/sqlcmd/RunnerConfig.java b/src/main/java/es/jdlopez/sqlcmd/RunnerConfig.java index ebb8ef0..72d8831 100644 --- a/src/main/java/es/jdlopez/sqlcmd/RunnerConfig.java +++ b/src/main/java/es/jdlopez/sqlcmd/RunnerConfig.java @@ -10,6 +10,16 @@ public class RunnerConfig { private String outputResult; private Boolean printHeader = true; private String printFieldSeparator = "\t"; + // mail configuration: + private String mailSendTo; + private String mailHost; + private String mailPort; + private Boolean mailAuth; + private Boolean mailTLS; + private String mailUser; + private String mailPass; + private String mailFrom; + private String mailSubject; public String getInputSQL() { return inputSQL; @@ -82,4 +92,76 @@ public String getPrintFieldSeparator() { public void setPrintFieldSeparator(String printFieldSeparator) { this.printFieldSeparator = printFieldSeparator; } + + public String getMailSendTo() { + return mailSendTo; + } + + public void setMailSendTo(String mailSendTo) { + this.mailSendTo = mailSendTo; + } + + public String getMailHost() { + return mailHost; + } + + public void setMailHost(String mailHost) { + this.mailHost = mailHost; + } + + public String getMailPort() { + return mailPort; + } + + public void setMailPort(String mailPort) { + this.mailPort = mailPort; + } + + public Boolean getMailAuth() { + return mailAuth; + } + + public void setMailAuth(Boolean mailAuth) { + this.mailAuth = mailAuth; + } + + public Boolean getMailTLS() { + return mailTLS; + } + + public void setMailTLS(Boolean mailTLS) { + this.mailTLS = mailTLS; + } + + public String getMailUser() { + return mailUser; + } + + public void setMailUser(String mailUser) { + this.mailUser = mailUser; + } + + public String getMailPass() { + return mailPass; + } + + public void setMailPass(String mailPass) { + this.mailPass = mailPass; + } + + public String getMailFrom() { + return mailFrom; + } + + public void setMailFrom(String mailFrom) { + this.mailFrom = mailFrom; + } + + public String getMailSubject() { + return mailSubject; + } + + public void setMailSubject(String mailSubject) { + this.mailSubject = mailSubject; + } } diff --git a/src/main/java/es/jdlopez/sqlcmd/SendMail.java b/src/main/java/es/jdlopez/sqlcmd/SendMail.java new file mode 100644 index 0000000..3afb26f --- /dev/null +++ b/src/main/java/es/jdlopez/sqlcmd/SendMail.java @@ -0,0 +1,59 @@ +package es.jdlopez.sqlcmd; + +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; + +public class SendMail { + + private Authenticator auth; + private Properties sessionProps; + private String from; + + public SendMail(String host, String port, String from) { + this(host, port, from, false, false, null, null); + } + public SendMail(String host, String port, String from, boolean auth, boolean tls, String user, String pass) { + this.from = from; + this.sessionProps = new Properties(); + sessionProps.setProperty("mail.smtp.host", host); + sessionProps.setProperty("mail.smtp.port", port); + if (auth) { + sessionProps.setProperty("mail.smtp.auth", "true"); + // just user pass authenticator + this.auth = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, pass); + } + }; + } + if (tls) + sessionProps.setProperty("mail.smtp.starttls.enable", "true"); + + } + + public void sendText(String subject, String body, String to) throws MessagingException { + Session session = Session.getInstance(sessionProps, auth); + Message msg = new MimeMessage(session); + + msg.setFrom(new InternetAddress(from)); + + msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); + + msg.setSubject(subject); + + msg.setText(body); + // Let's tranport sets default value + //msg.setHeader("X-Mailer", mailer); + //msg.setSentDate(new Date()); + + Transport.send(msg); + } +} diff --git a/src/test/java/es/jdlopez/sqlcmd/TestMain.java b/src/test/java/es/jdlopez/sqlcmd/TestMain.java new file mode 100644 index 0000000..e66b37d --- /dev/null +++ b/src/test/java/es/jdlopez/sqlcmd/TestMain.java @@ -0,0 +1,24 @@ +package es.jdlopez.sqlcmd; + +import org.junit.Test; + +import java.io.FileReader; +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.Properties; + +public class TestMain { + + @Test + public void testCreateTable() throws Exception { + // create table must be in previous statement: hsqldb docs + Properties p = new Properties(); + p.load(new FileReader("src/test/resources/sample.properties")); + Connection conn = DriverManager.getConnection(p.getProperty("jdbcUrl"), + p.getProperty("jdbcUser"), p.getProperty("jdbcPass")); + conn.createStatement().executeUpdate("create table testtable1 ( field1 int, field2 varchar(10))"); + String[] args = new String[]{"-c:src/test/resources/sample.properties", "-p:inputSQL=src/test/resources/test1.sql"}; + MainRunner.main(args); + conn.createStatement().executeUpdate("drop table testtable1"); + } +} diff --git a/src/test/resources/sample.properties b/src/test/resources/sample.properties index 273eda8..6531d81 100644 --- a/src/test/resources/sample.properties +++ b/src/test/resources/sample.properties @@ -1,6 +1,13 @@ # database connection properties -jdbcDriverPath= -jdbcDriverClass= -jdbcUrl= -jdbcUser= +#jdbcDriverPath= +#jdbcDriverClass= +jdbcUrl=jdbc:hsqldb:mem:mymemdb +jdbcUser=SA jdbcPass= + +# mail config +mailFrom=noreply@example.com +mailSubject=SqlCmd subject sent +mailSendTo=nobody@example.com +mailHost=localhost +mailPort=25 diff --git a/src/test/resources/test1.sql b/src/test/resources/test1.sql new file mode 100644 index 0000000..92b4a56 --- /dev/null +++ b/src/test/resources/test1.sql @@ -0,0 +1,15 @@ +insert into testtable1 (field1, field2) +values +(1, 'one'), +(2, 'two'), +(3, 'three'), +(4, 'four'), +(5, 'five'); + +select * from testtable1; + +insert into testtable1 (field1, field2) +values + (6, 'six') + +select field2, field1, 'fiexed value' as fixxedd from testtable1;