-
Notifications
You must be signed in to change notification settings - Fork 11
/
sql7.sd7
277 lines (262 loc) · 9.56 KB
/
sql7.sd7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
(********************************************************************)
(* *)
(* sql7.sd7 Sql command line tool *)
(* Copyright (C) 2014, 2017 Thomas Mertes *)
(* *)
(* This program is free software; you can redistribute it and/or *)
(* modify it under the terms of the GNU General Public License as *)
(* published by the Free Software Foundation; either version 2 of *)
(* the License, or (at your option) any later version. *)
(* *)
(* This program is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU General Public License for more details. *)
(* *)
(* You should have received a copy of the GNU General Public *)
(* License along with this program; if not, write to the *)
(* Free Software Foundation, Inc., 51 Franklin Street, *)
(* Fifth Floor, Boston, MA 02110-1301, USA. *)
(* *)
(********************************************************************)
$ include "seed7_05.s7i";
include "keybd.s7i";
include "console.s7i";
include "osfiles.s7i";
include "editline.s7i";
include "sql_base.s7i";
include "utf8.s7i";
const proc: writeHelp is func
begin
writeln("usage: sql7 driver dbName user [password [sqlFile]]");
writeln;
writeln("The following drivers are supported: ");
writeln(" Driver Shortcut Database");
writeln(" MYSQL MY MySql/MariaDb");
writeln(" SQLITE LITE SQLLite");
writeln(" POSTGRESQL POST PostgreSQL");
writeln(" ORACLE OCI Oracle");
writeln(" ODBC Odbc");
writeln(" FIREBIRD FIRE Firebird/Interbase");
writeln(" DB2 Db2");
writeln(" SQL_SERVER SQLSRV SQL Server");
writeln;
writeln("The database name (dbName) can be specified with or without host name:");
writeln(" myDb");
writeln(" www.example.org/myDb");
writeln(" 192.0.1.250/myDb");
writeln;
writeln("Sql7 accepts SQL commands of the connected database.");
writeln("Commands to exit sql7: exit, quit");
writeln;
end func;
const func boolean: failed (in proc: statement) is func
result
var boolean: failed is FALSE;
begin
block
statement;
exception
catch RANGE_ERROR:
failed := TRUE;
catch FILE_ERROR:
failed := TRUE;
catch DATABASE_ERROR:
failed := TRUE;
end block;
end func;
const proc: displayResult (in sqlStatement: statement) is func
local
const integer: width is 20;
var integer: index is 0;
begin
for index range 1 to columnCount(statement) do
write(columnName(statement, index) rpad width <& " ");
end for;
writeln;
writeln(("-" mult width & " ") mult columnCount(statement));
while fetch(statement) do
for index range 1 to columnCount(statement) do
if failed(write(noCtrlChars(column(statement, index, string)[1 len width]) rpad width <& " ")) and
failed(write( column(statement, index, integer) lpad width <& " ")) and
failed(write( column(statement, index, bigInteger) lpad width <& " ")) and
failed(write( column(statement, index, bigRational) lpad width <& " ")) and
failed(write( column(statement, index, float) sci width - 7 exp 2 lpad width <& " ")) and
failed(write(strDateTime(column(statement, index, time)) rpad width <& " ")) and
failed(write( column(statement, index, duration) rpad width <& " ")) and
failed(write( column(statement, index, boolean) lpad width <& " ")) then
write("*" mult width <& " ");
end if;
end for;
writeln;
end while;
end func;
const proc: doExecute (in database: currDb, in var string: command) is func
local
var sqlStatement: statement is sqlStatement.value;
var boolean: failed is FALSE;
begin
if endsWith(command, ";") then
command := command[.. pred(length(command))];
end if;
block
statement := prepare(currDb, command);
execute(statement);
exception
catch DATABASE_ERROR:
writeln;
writeln(command);
writeln(" *** Database error: " <& errMessage(DATABASE_ERROR));
writeln;
failed := TRUE;
otherwise:
writeln;
writeln(command);
writeln(" *** Error occurred");
writeln;
failed := TRUE;
end block;
if not failed then
if columnCount(statement) <> 0 then
displayResult(statement);
else
writeln;
writeln("Success.");
writeln;
end if;
end if;
end func;
const func string: getSqlStatement (inout file: inFile) is func
result
var string: sqlStatement is "";
local
var char: ch is ' ';
var char: delimiter is ' ';
begin
ch := getc(inFile);
while ch <> ';' and ch <> EOF do
if ch = ''' or ch = '"' then
delimiter := ch;
sqlStatement &:= delimiter;
ch := getc(inFile);
while ch <> delimiter and ch <> EOF do
sqlStatement &:= ch;
ch := getc(inFile);
end while;
if ch = delimiter then
sqlStatement &:= delimiter;
ch := getc(inFile);
end if;
elsif ch = '/' then
ch := getc(inFile);
if ch <> '*' or ch = EOF then
sqlStatement &:= '/';
else
ch := getc(inFile);
repeat
while ch <> '*' and ch <> EOF do
ch := getc(inFile);
end while;
ch := getc(inFile);
until ch = '/' or ch = EOF;
ch := getc(inFile);
end if;
elsif ch = '-' then
ch := getc(inFile);
if ch <> '-' or ch = EOF then
sqlStatement &:= '-';
else
ch := getc(inFile);
while ch <> '\n' and ch <> EOF do
ch := getc(inFile);
end while;
end if;
else
sqlStatement &:= ch;
ch := getc(inFile);
end if;
end while;
inFile.bufferChar := ch;
end func;
const proc: main is func
local
var string: fileName is "";
var file: sqlFile is STD_NULL;
var string: driverName is "";
var dbCategory: driver is NO_DB;
var string: password is "";
var database: currDb is database.value;
var string: command is "";
begin
OUT := STD_CONSOLE;
IN := openEditLine(KEYBOARD, OUT);
if length(argv(PROGRAM)) = 5 then
fileName := convDosPath(argv(PROGRAM)[5]);
sqlFile := openUtf8(fileName, "r");
end if;
if sqlFile = STD_NULL then
writeln("Sql7 - Sql command line tool");
writeln("Copyright (C) 2014 Thomas Mertes");
writeln("This is free software; see the source for copying conditions. There is NO");
writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
writeln("Sql7 is written in the Seed7 programming language");
writeln("Homepage: http://seed7.sourceforge.net");
writeln;
end if;
if length(argv(PROGRAM)) = 0 then
writeln("Use sql7 -? to get more information about sql7.");
writeln;
elsif length(argv(PROGRAM)) = 1 and argv(PROGRAM)[1] = "-?" then
writeHelp;
elsif length(argv(PROGRAM)) not in {3, 4, 5} then
writeln("usage: sql7 driver dbName user [password [sqlfile]]");
elsif length(argv(PROGRAM)) = 5 and sqlFile = STD_NULL then
writeln(" *** Cannot open " <& fileName);
else
driverName := argv(PROGRAM)[1];
driver := dbCategory(driverName);
if driver = NO_DB then
writeln("*** " <& literal(driverName) <& " is not a valid database driver.");
else
if length(argv(PROGRAM)) = 3 then
write("Password: ");
flush(OUT);
password := readPassword(IN);
else
password := argv(PROGRAM)[4];
end if;
block
currDb := openDatabase(driver, argv(PROGRAM)[2], argv(PROGRAM)[3], password);
exception
catch DATABASE_ERROR:
writeln(" *** Database error: " <& errMessage(DATABASE_ERROR));
otherwise:
writeln(" *** Cannot open " <& argv(PROGRAM)[2]);
end block;
if currDb <> database.value then
if sqlFile <> STD_NULL then
while hasNext(sqlFile) do
command := getSqlStatement(sqlFile);
command := trim(command);
if command <> "" then
# writeln(literal(command));
doExecute(currDb, command);
end if;
end while;
close(sqlFile);
else
write("Sql7? ");
readln(command);
while lower(command) <> "exit" and lower(command) <> "quit" do
if command <> "" then
doExecute(currDb, command);
end if;
write("Sql7? ");
readln(command);
end while;
end if;
close(currDb);
end if;
end if;
end if;
end func;