select queries now work, and print tabular output.
[squelch.git] / src / main / java / net / jaekl / squelch / Squelch.java
1 package net.jaekl.squelch;
2
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.sql.Connection;
6 import java.sql.SQLException;
7 import java.util.Locale;
8
9 import net.jaekl.squelch.db.DbDriver;
10 import net.jaekl.squelch.db.MsSqlDriver;
11 import net.jaekl.squelch.db.MySqlDriver;
12 import net.jaekl.squelch.db.OracleDriver;
13 import net.jaekl.squelch.db.PostgresqlDriver;
14 import net.jaekl.squelch.stmt.Select;
15 import net.jaekl.squelch.stmt.Stmt;
16 import net.jaekl.squelch.util.ConsoleInput;
17 import net.jaekl.squelch.util.ConsoleInputImpl;
18 import net.jaekl.squelch.util.ConsoleUtil;
19
20 public class Squelch {
21         static final String PROMPT = "> ";
22         private static final DbDriver[] DB_DRIVERS = {
23                 new MsSqlDriver(),
24                 new MySqlDriver(),
25                 new OracleDriver(),
26                 new PostgresqlDriver()
27         };
28         private static final Stmt[] READ_ONLY_STATEMENTS = {
29                 new Select()
30         };
31         
32         private Args m_args;
33         private Stmt[] m_statements;
34
35         public Squelch() {
36                 m_args = new Args(this.getClass().getName());
37                 m_statements = READ_ONLY_STATEMENTS;
38         }
39         
40         public void doMain(String[] params)
41         {
42                 try (PrintWriter pw = new PrintWriter(System.out))
43                 {
44                         if (!m_args.parseArgs(pw, params)) {
45                                 return;
46                         }
47                         
48                         ConsoleInputImpl ci = ConsoleUtil.getInst().getInput();
49                         pumpLines(pw, ci);                      
50                 } catch (IOException | ClassNotFoundException | SQLException | SquelchException e) {
51                         e.printStackTrace();
52                 }
53         }
54         
55         public static void main(String[] args) {
56                 new Squelch().doMain(args);
57         }
58         
59         boolean isQuit(String line) 
60         {
61                 if ((null == line)) {
62                         return true;
63                 }
64                 String trimmed = line.trim();
65                 if (trimmed.endsWith(";")) {
66                         trimmed = trimmed.substring(0, trimmed.length() - 1).trim();
67                 }
68                 String upperCased = trimmed.toUpperCase(Locale.CANADA);
69                 
70                 if (  "EXIT".equals(upperCased)
71                    || "QUIT".equals(upperCased)
72                    || "\\q".equals(trimmed) ) 
73                 {
74                         return true;
75                 }
76                 return false;
77         }
78         
79         Connection getConnection() throws ClassNotFoundException, SQLException, SquelchException 
80         {
81                 String jdbcUrl = m_args.getUrl();
82                 DbDriver driver = getDriverFor(jdbcUrl);
83
84                 return driver.connect(jdbcUrl, m_args.getUser(), m_args.getPass());
85         }
86         
87         DbDriver getDriverFor(String jdbcUrl) throws SquelchException 
88         {
89                 for (DbDriver driver : DB_DRIVERS) {
90                         if (driver.handles(jdbcUrl)) {
91                                 return driver;
92                         }
93                 }
94                 throw new SquelchException("Cannot determine DB Driver for JDBC URL:  \"" + jdbcUrl + "\".");
95         }
96         
97         void pumpLines(PrintWriter pw, ConsoleInput ci) throws IOException, ClassNotFoundException, SQLException, SquelchException 
98         {
99                 String line = null;
100                 try (Connection conn = getConnection())
101                 {
102                         while (true) {
103                                 boolean processed = false;
104                                 line = ci.readLine(PROMPT);
105                                 
106                                 for (Stmt statement : m_statements) {
107                                         if (statement.handles(line)) {
108                                                 statement.exec(conn, pw, line);
109                                                 processed = true;
110                                                 break;
111                                         }
112                                 }
113                                 
114                                 if ((!processed)) {
115                                         if (isQuit(line)) {
116                                                 break;
117                                         }
118                                         // Unrecognized command
119                                         // TODO:  add a string table, and a natural-language error message.
120                                         pw.println("??? \"" + line + "\"");
121                                         pw.flush();
122                                 }
123                         }
124                 }
125         }       
126 }