1 /** 2 * ae.demo.sqlite.exec 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.demo.sqlite.exec; 15 16 import std.stdio; 17 import std.algorithm; 18 import std.array; 19 import std.conv; 20 import std.datetime; 21 22 import ae.sys.sqlite3; 23 import ae.sys.console; 24 25 void main(string[] args) 26 { 27 if (args.length < 2 || args.length > 3) 28 return stderr.writeln("Usage: exec DATABASE [COMMAND]"); 29 30 auto db = new SQLite(args[1]); 31 32 void exec(string sql, bool interactive) 33 { 34 int idx = 0; 35 string[][] rows; 36 StopWatch sw; 37 sw.start(); 38 foreach (cells, columns; db.query(sql)) 39 { 40 sw.stop(); 41 if (rows is null) 42 rows ~= ["#"] ~ array(map!`a.idup`(columns)); 43 rows ~= [to!string(idx++)] ~ array(map!`a.idup`(cells)); 44 sw.start(); 45 } 46 sw.stop(); 47 if (interactive || rows.length == 0) 48 stderr.writeln("Query executed in ", dur!"hnsecs"(sw.peek().hnsecs).toString().replace("μ", "u")); 49 50 if (rows.length == 0) 51 return; 52 auto widths = new size_t[rows[0].length]; 53 foreach (row; rows) 54 { 55 assert(row.length == rows[0].length); 56 foreach (i, cell; row) 57 widths[i] = max(widths[i], textWidth(cell)); 58 } 59 foreach (j, row; rows) 60 { 61 auto rowLines = array(map!textLines(row)); 62 auto lineCount = reduce!max(map!`a.length`(rowLines)); 63 64 foreach (line; 0..lineCount) 65 { 66 foreach (i, lines; rowLines) 67 { 68 if (i) write(" │ "); 69 string col = line < lines.length ? lines[line] : null; 70 write(col, std.array.replicate(" ", widths[i]-col.length)); 71 } 72 writeln(); 73 } 74 if (j==0) 75 { 76 foreach (i, w; widths) 77 { 78 if (i) write("─┼─"); 79 write(std.array.replicate("─", w)); 80 } 81 writeln(); 82 } 83 } 84 writeln(); 85 } 86 87 if (args.length == 3) 88 exec(args[2], false); 89 else 90 while (!stdin.eof()) 91 { 92 write("sqlite> "); 93 stdout.flush(); 94 try 95 exec(readln().chomp(), true); 96 catch (Exception e) 97 writeln(e.msg); 98 } 99 } 100 101 import std.utf; 102 import std.string; 103 104 size_t textWidth(string s) 105 { 106 try 107 { 108 auto lines = splitLines(s); 109 size_t w = 0; 110 foreach (line; lines) 111 w = max(w, std.utf.count(line)); 112 return w; 113 } 114 catch (Exception e) 115 return s.length; 116 } 117 118 string[] textLines(string s) 119 { 120 try 121 return splitLines(s); 122 catch (Exception e) 123 return [s]; 124 }