1417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughespackage SQLite;
2417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
3417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesimport SQLite.*;
4417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesimport java.io.*;
5417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesimport java.util.*;
6417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
7417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes/**
8417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * SQLite command line shell. This is a partial reimplementaion
9417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * of sqlite/src/shell.c and can be invoked by:<P>
10417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes *
11417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * <verb>
12417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes *     java SQLite.Shell [OPTIONS] database [SHELLCMD]
13417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * or
14417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes *     java -jar sqlite.jar [OPTIONS] database [SHELLCMD]
15417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * </verb>
16417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes */
17417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
18417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughespublic class Shell implements Callback {
19417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    Database db;
20417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    boolean echo;
21417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    int count;
22417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    int mode;
23417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    boolean showHeader;
24417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    String tableName;
25417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    String sep;
26417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    String cols[];
27417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    int colwidth[];
28417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    String destTable;
29417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    PrintWriter pw;
30417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    PrintWriter err;
31417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
32417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Line = 0;
33417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Column = 1;
34417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_List = 2;
35417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Semi = 3;
36417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Html = 4;
37417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Insert = 5;
38417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static final int MODE_Insert2 = 6;
39417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
40417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public Shell(PrintWriter pw, PrintWriter err) {
417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	this.pw = pw;
427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	this.err = err;
43417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
44417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
45417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public Shell(PrintStream ps, PrintStream errs) {
467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	pw = new PrintWriter(ps);
477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	err = new PrintWriter(errs);
48417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
49417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
50417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    protected Object clone() {
51417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        Shell s = new Shell(this.pw, this.err);
527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.db = db;
537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.echo = echo;
547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.mode = mode;
557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.count = 0;
567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.showHeader = showHeader;
577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.tableName = tableName;
587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.sep = sep;
597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.colwidth = colwidth;
607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return s;
61417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
62417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
63417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static public String sql_quote_dbl(String str) {
647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (str == null) {
657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "NULL";
667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	int i, single = 0, dbl = 0;
687a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (i = 0; i < str.length(); i++) {
697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (str.charAt(i) == '\'') {
707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		single++;
717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (str.charAt(i) == '"') {
727a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		dbl++;
737a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
747a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (dbl == 0) {
767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "\"" + str + "\"";
777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	StringBuffer sb = new StringBuffer("\"");
797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (i = 0; i < str.length(); i++) {
807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    char c = str.charAt(i);
817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (c == '"') {
827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append("\"\"");
837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append(c);
857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return sb.toString();
88417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
89417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
90417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static public String sql_quote(String str) {
917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (str == null) {
927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "NULL";
937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	int i, single = 0, dbl = 0;
957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (i = 0; i < str.length(); i++) {
967a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (str.charAt(i) == '\'') {
977a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		single++;
987a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (str.charAt(i) == '"') {
997a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		dbl++;
1007a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1017a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1027a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (single == 0) {
1037a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "'" + str + "'";
1047a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1057a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (dbl == 0) {
1067a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "\"" + str + "\"";
1077a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1087a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	StringBuffer sb = new StringBuffer("'");
1097a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (i = 0; i < str.length(); i++) {
1107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    char c = str.charAt(i);
1117a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (c == '\'') {
1127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append("''");
1137a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
1147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append(c);
1157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return sb.toString();
118417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
119417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
120417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static String html_quote(String str) {
1217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (str == null) {
1227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return "NULL";
1237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	StringBuffer sb = new StringBuffer();
1257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (int i = 0; i < str.length(); i++) {
1267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    char c = str.charAt(i);
1277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (c == '<') {
1287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append("&lt;");
1297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (c == '>') {
1307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append("&gt;");
1317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (c == '&') {
1327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sb.append("&amp;");
1337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
1347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		int x = c;
1357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (x < 32 || x > 127) {
1367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    sb.append("&#" + x + ";");
1377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else {
1387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    sb.append(c);
1397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
1407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return sb.toString();
143417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
144417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
145417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    static boolean is_numeric(String str) {
1467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	try {
1477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    Double d = Double.valueOf(str);
1487a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} catch (java.lang.Exception e) {
1497a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return false;
1507a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return true;
152417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
153417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
154417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    void set_table_name(String str) {
1557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (str == null) {
1567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    tableName = "";
1577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
1587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
1597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (db.is3()) {
1607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    tableName = Shell.sql_quote_dbl(str);
1617a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} else {
1627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    tableName = Shell.sql_quote(str);
1637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
164417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
165417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
166417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public void columns(String args[]) {
1677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	cols = args;
168417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
169417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
170417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public void types(String args[]) {
1717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	/* Empty body to satisfy SQLite.Callback interface. */
172417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
173417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
174417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public boolean newrow(String args[]) {
1757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	int i;
1767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String tname;
1777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	switch (mode) {
1787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case Shell.MODE_Line:
1797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
1807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
1817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (count++ > 0) {
1837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.println("");
1847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
1867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.println(cols[i] + " = " +
1877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			   args[i] == null ? "NULL" : args[i]);
1887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
1897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
1907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case Shell.MODE_Column:
1917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    String csep = "";
1927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (count++ == 0) {
1937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		colwidth = new int[args.length];
1947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		for (i = 0; i < args.length; i++) {
1957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    int w, n;
1967a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    w = cols[i].length();
1977a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    if (w < 10) {
1987a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			w = 10;
1997a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
2007a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    colwidth[i] = w;
2017a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    if (showHeader) {
2027a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			pw.print(csep + cols[i]);
2037a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			csep = " ";
2047a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
2057a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2067a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (showHeader) {
2077a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.println("");
2087a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2097a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
2117a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
2127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2137a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    csep = "";
2147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
2157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print(csep + (args[i] == null ? "NULL" : args[i]));
2167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		csep = " ";
2177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println("");
2197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
2207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case Shell.MODE_Semi:
2217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case Shell.MODE_List:
2227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (count++ == 0 && showHeader) {
2237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		for (i = 0; i < args.length; i++) {
2247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(cols[i] +
2257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			     (i == args.length - 1 ? "\n" : sep));
2267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
2297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
2307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
2327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print(args[i] == null ? "NULL" : args[i]);
2337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (mode == Shell.MODE_Semi) {
2347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(";");
2357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (i < args.length - 1) {
2367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(sep);
2377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println("");
2407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
2417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case MODE_Html:
2427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (count++ == 0 && showHeader) {
2437a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print("<TR>");
2447a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		for (i = 0; i < args.length; i++) {
2457a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print("<TH>" + html_quote(cols[i]) + "</TH>");
2467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.println("</TR>");
2487a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2497a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
2507a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
2517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.print("<TR>");
2537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
2547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print("<TD>" + html_quote(args[i]) + "</TD>");
2557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println("</TR>");
2577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
2587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case MODE_Insert:
2597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
2607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
2617a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    tname = tableName;
2637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (destTable != null) {
2647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        tname = destTable;
2657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.print("INSERT INTO " + tname + " VALUES(");
2677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
2687a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        String tsep = i > 0 ? "," : "";
2697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (args[i] == null) {
2707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(tsep + "NULL");
2717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (is_numeric(args[i])) {
2727a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(tsep + args[i]);
2737a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else {
2747a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    pw.print(tsep + sql_quote(args[i]));
2757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
2767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(");");
2787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
2797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	case MODE_Insert2:
2807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length == 0) {
2817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		break;
2827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    tname = tableName;
2847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (destTable != null) {
2857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        tname = destTable;
2867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.print("INSERT INTO " + tname + " VALUES(");
2887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (i = 0; i < args.length; i++) {
2897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        String tsep = i > 0 ? "," : "";
2907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print(tsep + args[i]);
2917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
2927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(");");
2937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    break;
2947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
2957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return false;
296417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
297417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
298417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    void do_meta(String line) {
299417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        StringTokenizer st = new StringTokenizer(line.toLowerCase());
3007a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	int n = st.countTokens();
3017a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (n <= 0) {
3027a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3037a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3047a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String cmd = st.nextToken();
3057a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String args[] = new String[n - 1];
3067a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	int i = 0;
3077a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	while (st.hasMoreTokens()) {
3087a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    args[i] = st.nextToken();
3097a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    ++i;
3107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3117a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".dump") == 0) {
3127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    new DBDump(this, args);
3137a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".echo") == 0) {
3167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0 &&
3177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		(args[0].startsWith("y") || args[0].startsWith("on"))) {
3187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		echo = true;
3197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
3207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".exit") == 0) {
3237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
3247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		db.close();
3257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
3267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
3277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    System.exit(0);
3287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".header") == 0) {
3307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0 &&
3317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		(args[0].startsWith("y") || args[0].startsWith("on"))) {
3327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		showHeader = true;
3337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
3347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".help") == 0) {
3377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".dump ?TABLE? ...  Dump database in text fmt");
3387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".echo ON|OFF       Command echo on or off");
3397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".enc ?NAME?        Change encoding");
3407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".exit              Exit program");
3417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".header ON|OFF     Display headers on or off");
3427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".help              This message");
3437a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".mode MODE         Set output mode to\n" +
3447a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		       "                   line, column, insert\n" +
3457a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		       "                   list, or html");
3467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".mode insert TABLE Generate SQL insert stmts");
3477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".schema ?PATTERN?  List table schema");
3487a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".separator STRING  Set separator string");
3497a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.println(".tables ?PATTERN?  List table names");
3507a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".mode") == 0) {
3537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0) {
3547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (args[0].compareTo("line") == 0) {
3557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    mode = Shell.MODE_Line;
3567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (args[0].compareTo("column") == 0) {
3577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    mode = Shell.MODE_Column;
3587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (args[0].compareTo("list") == 0) {
3597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    mode = Shell.MODE_List;
3607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (args[0].compareTo("html") == 0) {
3617a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    mode = Shell.MODE_Html;
3627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else if (args[0].compareTo("insert") == 0) {
3637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    mode = Shell.MODE_Insert;
3647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    if (args.length > 1) {
3657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			destTable = args[1];
3667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
3677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
3687a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
3697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".separator") == 0) {
3727a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0) {
3737a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sep = args[0];
3747a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
3757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
3767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
3777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".tables") == 0) {
3787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    TableResult t = null;
3797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0) {
3807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		try {
3817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    String qarg[] = new String[1];
3827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    qarg[0] = args[0];
3837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    t = db.get_table("SELECT name FROM sqlite_master " +
3847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes				     "WHERE type='table' AND " +
3857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes				     "name LIKE '%%%q%%' " +
3867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes				     "ORDER BY name", qarg);
3877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} catch (Exception e) {
3887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.println("SQL Error: " + e);
3897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.flush();
3907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
3917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
3927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		try {
3937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    t = db.get_table("SELECT name FROM sqlite_master " +
3947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes				     "WHERE type='table' ORDER BY name");
3957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} catch (Exception e) {
3967a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.println("SQL Error: " + e);
3977a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.flush();
3987a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
3997a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4007a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (t != null) {
4017a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		for (i = 0; i < t.nrows; i++) {
4027a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    String tab = ((String[]) t.rows.elementAt(i))[0];
4037a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    if (tab != null) {
4047a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			pw.println(tab);
4057a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
4067a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
4077a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4087a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
4097a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
4107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".schema") == 0) {
4117a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (args.length > 0) {
4127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		try {
4137a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    String qarg[] = new String[1];
4147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    qarg[0] = args[0];
4157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    db.exec("SELECT sql FROM sqlite_master " +
4167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "WHERE type!='meta' AND " +
4177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "name LIKE '%%%q%%' AND " +
4187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "sql NOTNULL " +
4197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "ORDER BY type DESC, name",
4207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    this, qarg);
4217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} catch (Exception e) {
4227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.println("SQL Error: " + e);
4237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.flush();
4247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
4257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
4267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		try {
4277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    db.exec("SELECT sql FROM sqlite_master " +
4287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "WHERE type!='meta' AND " +
4297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "sql NOTNULL " +
4307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    "ORDER BY tbl_name, type DESC, name",
4317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    this);
4327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} catch (Exception e) {
4337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.println("SQL Error: " + e);
4347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    err.flush();
4357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
4367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
4387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
4397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".enc") == 0) {
4407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
4417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		db.set_encoding(args.length > 0 ? args[0] : null);
4427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
4437a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.println("" + e);
4447a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.flush();
4457a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
4477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
4487a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (cmd.compareTo(".rekey") == 0) {
4497a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
4507a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		db.rekey(args.length > 0 ? args[0] : null);
4517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
4527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.println("" + e);
4537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.flush();
4547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
4567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
4577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	err.println("Unknown command '" + cmd + "'");
4587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	err.flush();
459417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
460417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
461417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    String read_line(BufferedReader is, String prompt) {
4627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	try {
4637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (prompt != null) {
4647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.print(prompt);
4657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.flush();
4667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    String line = is.readLine();
4687a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return line;
4697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} catch (IOException e) {
4707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return null;
4717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
472417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
473417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
474417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    void do_input(BufferedReader is) {
4757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String line, sql = null;
4767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String prompt = "SQLITE> ";
4777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	while ((line = read_line(is, prompt)) != null) {
4787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (echo) {
4797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		pw.println(line);
4807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
4817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if (line.length() > 0 && line.charAt(0) == '.') {
4827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        do_meta(line);
4837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
4847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (sql == null) {
4857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    sql = line;
4867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else {
4877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    sql = sql + " " + line;
4887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
4897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		if (Database.complete(sql)) {
4907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    try {
4917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			db.exec(sql, this);
4927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    } catch (Exception e) {
4937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			if (!echo) {
4947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    err.println(sql);
4957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			}
4967a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			err.println("SQL Error: " + e);
4977a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			err.flush();
4987a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
4997a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    sql = null;
5007a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    prompt = "SQLITE> ";
5017a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else {
5027a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    prompt = "SQLITE? ";
5037a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
5047a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
5057a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    pw.flush();
5067a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5077a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (sql != null) {
5087a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    err.println("Incomplete SQL: " + sql);
5097a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    err.flush();
5107a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
511417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
512417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
513417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    void do_cmd(String sql) {
514417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        if (db == null) {
5157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return;
5167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
517417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        if (sql.length() > 0 && sql.charAt(0) == '.') {
5187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    do_meta(sql);
5197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} else {
5207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
5217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        db.exec(sql, this);
5227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
5237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.println("SQL Error: " + e);
5247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		err.flush();
5257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
5267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
527417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
528417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
529417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public static void main(String args[]) {
5307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String key = null;
5317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	Shell s = new Shell(System.out, System.err);
5327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.mode = Shell.MODE_List;
5337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.sep = "|";
5347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.showHeader = false;
5357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.db = new Database();
5367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	String dbname = null, sql = null;
5377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	for (int i = 0; i < args.length; i++) {
5387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    if(args[i].compareTo("-html") ==0) {
5397a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.mode = Shell.MODE_Html;
5407a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-list") == 0) {
5417a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.mode = Shell.MODE_List;
5427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-line") == 0) {
5437a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.mode = Shell.MODE_Line;
5447a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (i < args.length - 1 &&
5457a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		       args[i].compareTo("-separator") == 0) {
5467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		++i;
5477a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.sep = args[i];
5487a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-header") == 0) {
5497a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.showHeader = true;
5507a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-noheader") == 0) {
5517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.showHeader = false;
5527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-echo") == 0) {
5537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.echo = true;
5547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (args[i].compareTo("-key") == 0) {
5557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		++i;
5567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		key = args[i];
5577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (dbname == null) {
5587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		dbname = args[i];
5597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else if (sql == null) {
5607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		sql = args[i];
5617a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } else {
5627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		System.err.println("Arguments: ?OPTIONS? FILENAME ?SQL?");
5637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		System.exit(1);
5647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
5657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (dbname == null) {
5677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    System.err.println("No database file given");
5687a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    System.exit(1);
5697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	try {
5717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.db.open(dbname, 0);
5727a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} catch (Exception e) {
5737a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    System.err.println("Unable to open database: " + e);
5747a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    System.exit(1);
5757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (key != null) {
5777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
5787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.db.key(key);
5797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
5807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		System.err.println("Unable to set key: " + e);
5817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		System.exit(1);
5827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
5837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (sql != null) {
5857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.do_cmd(sql);
5867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.pw.flush();
5877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} else {
5887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    BufferedReader is =
5897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		new BufferedReader(new InputStreamReader(System.in));
5907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.do_input(is);
5917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.pw.flush();
5927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
5937a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	try {
5947a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s.db.close();
5957a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} catch (Exception ee) {
5967a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
597417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
598417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes}
599417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
600417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes/**
601417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * Internal class for dumping an entire database.
602417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * It contains a special callback interface to traverse the
603417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * tables of the current database and output create SQL statements
604417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes * and for the data insert SQL statements.
605417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes */
606417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
607417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughesclass DBDump implements Callback {
608417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    Shell s;
609417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
610417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    DBDump(Shell s, String tables[]) {
611417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        this.s = s;
6127a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.pw.println("BEGIN TRANSACTION;");
613417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        if (tables == null || tables.length == 0) {
6147a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
6157a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        s.db.exec("SELECT name, type, sql FROM sqlite_master " +
6167a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			  "WHERE type!='meta' AND sql NOT NULL " +
6177a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			  "ORDER BY substr(type,2,1), name", this);
6187a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
6197a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        s.err.println("SQL Error: " + e);
6207a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.err.flush();
6217a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
6227a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	} else {
6237a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    String arg[] = new String[1];
6247a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    for (int i = 0; i < tables.length; i++) {
6257a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        arg[0] = tables[i];
6267a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		try {
6277a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    s.db.exec("SELECT name, type, sql FROM sqlite_master " +
6287a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			      "WHERE tbl_name LIKE '%q' AND type!='meta' " +
6297a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			      " AND sql NOT NULL " +
6307a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			      " ORDER BY substr(type,2,1), name",
6317a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			      this, arg);
6327a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} catch (Exception e) {
6337a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    s.err.println("SQL Error: " + e);
6347a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    s.err.flush();
6357a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
6367a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
6377a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
6387a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.pw.println("COMMIT;");
639417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
640417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
641417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public void columns(String col[]) {
6427a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	/* Empty body to satisfy SQLite.Callback interface. */
643417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
644417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
645417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public void types(String args[]) {
6467a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	/* Empty body to satisfy SQLite.Callback interface. */
647417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
648417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
649417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    public boolean newrow(String args[]) {
650417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes        if (args.length != 3) {
6517a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    return true;
6527a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
6537a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	s.pw.println(args[2] + ";");
6547a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	if (args[1].compareTo("table") == 0) {
6557a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    Shell s2 = (Shell) s.clone();
6567a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s2.mode = Shell.MODE_Insert;
6577a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    s2.set_table_name(args[0]);
6587a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    String qargs[] = new String[1];
6597a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    qargs[0] = args[0];
6607a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    try {
6617a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        if (s2.db.is3()) {
6627a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    TableResult t = null;
6637a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    t = s2.db.get_table("PRAGMA table_info('%q')", qargs);
6647a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    String query;
6657a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    if (t != null) {
6667a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		        StringBuffer sb = new StringBuffer();
6677a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			String sep = "";
668417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes
6697a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			sb.append("SELECT ");
6707a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			for (int i = 0; i < t.nrows; i++) {
6717a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    String col = ((String[]) t.rows.elementAt(i))[1];
6727a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    sb.append(sep + "quote(" +
6737a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes				      Shell.sql_quote_dbl(col) + ")");
6747a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			    sep = ",";
6757a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			}
6767a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			sb.append(" from '%q'");
6777a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			query = sb.toString();
6787a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes			s2.mode = Shell.MODE_Insert2;
6797a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    } else {
6807a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		        query = "SELECT * from '%q'";
6817a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    }
6827a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    s2.db.exec(query, s2, qargs);
6837a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		} else {
6847a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		    s2.db.exec("SELECT * from '%q'", s2, qargs);
6857a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		}
6867a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    } catch (Exception e) {
6877a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	        s.err.println("SQL Error: " + e);
6887a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		s.err.flush();
6897a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes		return true;
6907a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	    }
6917a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	}
6927a647e8547e57ca573541be55b3728ef7ce376feElliott Hughes	return false;
693417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes    }
694417deb1db112103aff04231b6ca79772ff7d3a21Elliott Hughes}
695