mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-15 12:38:36 +02:00
297 lines
6.5 KiB
ObjectPascal
297 lines
6.5 KiB
ObjectPascal
{$mode objfpc}
|
|
{$h+}
|
|
uses
|
|
custapp, sysutils, strutils, classes, db, sqldb, bufdataset, XMLDatapacketReader,
|
|
sqlite3conn, pqconnection, ibconnection, mssqlconn, oracleconnection,mysql55conn,mysql40conn,mysql51conn,mysql50conn;
|
|
|
|
Const
|
|
CmdSep = [' ',#9,#10,#13,#12];
|
|
|
|
type
|
|
|
|
{ TSQLShellApplication }
|
|
|
|
TSQLShellApplication = class(TCustomApplication)
|
|
Private
|
|
FConn : TSQLConnection;
|
|
FTR : TSQLTransaction;
|
|
FQuery : TSQLQuery;
|
|
FConnType : String;
|
|
FCharset : String;
|
|
FDatabaseName: String;
|
|
FHostName : string;
|
|
FUserName : String;
|
|
FPassword : String;
|
|
FPort : INteger;
|
|
FAutoCommit : Boolean;
|
|
procedure ConnectToDatabase;
|
|
procedure DisconnectFromDatabase;
|
|
procedure ExecuteCommand(const ASQL: UTF8String);
|
|
procedure ExecuteSystemCommand(const S : UTF8String);
|
|
procedure MaybeCommit;
|
|
procedure MaybeRollBack;
|
|
function ParseArgs: Boolean;
|
|
procedure RunCommandLoop;
|
|
procedure SaveLast(FN: String);
|
|
procedure Usage(const Err: String);
|
|
procedure WriteHelp;
|
|
Protected
|
|
procedure DoRun; override;
|
|
Property Conn : TSQLConnection Read FConn;
|
|
Property AutoCommit : Boolean Read FAutoCommit;
|
|
end;
|
|
|
|
|
|
Procedure TSQLShellApplication.ConnectToDatabase;
|
|
|
|
begin
|
|
FConn:=TSQLConnector.Create(Self);
|
|
TSQLConnector(FConn).ConnectorType:=FConnType;
|
|
FTR:=TSQLTransaction.Create(Self);
|
|
Conn.Transaction:=FTR;
|
|
Conn.DatabaseName:=FDatabaseName;
|
|
Conn.HostName:=FHostName;
|
|
Conn.UserName:=FUserName;
|
|
Conn.Password:=FPassword;
|
|
Conn.Connected:=True;
|
|
if FCharset<>'' then
|
|
Conn.CharSet:=FCharset;
|
|
end;
|
|
|
|
|
|
Procedure TSQLShellApplication.DisconnectFromDatabase;
|
|
|
|
begin
|
|
FreeAndNil(FTr);
|
|
FreeAndNil(FConn);
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.ExecuteCommand(Const ASQL : UTF8String);
|
|
|
|
Var
|
|
Q : TSQLQuery;
|
|
F : TField;
|
|
|
|
begin
|
|
FreeAndNil(FQuery);
|
|
Q:=TSQLQuery.Create(Conn);
|
|
Q.Database:=Conn;
|
|
Q.Transaction:=FTr;
|
|
if not FTR.Active then
|
|
FTR.StartTransaction;
|
|
Q.SQL.Text:=aSQL;
|
|
Q.Prepare;
|
|
if Q.StatementType<>stSelect then
|
|
begin
|
|
Q.ExecSQL;
|
|
Writeln('Rows affected : ',Q.RowsAffected);
|
|
if AutoCommit then
|
|
(Q.Transaction as TSQLTransaction).Commit;
|
|
Q.Free;
|
|
end
|
|
else
|
|
begin
|
|
Q.Open;
|
|
Write('|');
|
|
For F in Q.Fields do
|
|
Write(' ',F.FieldName,' |');
|
|
Writeln;
|
|
While not Q.EOF do
|
|
begin
|
|
Write('|');
|
|
For F in Q.Fields do
|
|
Write(F.AsString,' |');
|
|
Writeln;
|
|
Q.Next;
|
|
end;
|
|
FQuery:=Q;
|
|
end;
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.SaveLast(FN : String);
|
|
|
|
begin
|
|
FN:=Trim(FN);
|
|
if FN='' then
|
|
begin
|
|
Write('Type filename to save data: ');
|
|
Readln(fn);
|
|
end;
|
|
if (FN<>'') then
|
|
FQuery.SaveToFile(FN,dfXML);
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.MaybeCommit;
|
|
begin
|
|
if FTR.Active then
|
|
FTR.Commit;
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.MaybeRollBack;
|
|
begin
|
|
if FTR.Active then
|
|
FTR.Commit;
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.ExecuteSystemCommand(Const S : UTF8String);
|
|
|
|
Var
|
|
Cmd,Args : String;
|
|
|
|
begin
|
|
Cmd:=ExtractWord(1,S,CmdSep);
|
|
Args:=S;
|
|
Delete(Args,1,Length(Cmd)+Pos(Cmd,Args)-1);
|
|
While (Length(Args)>0) and (Args[1] in CmdSep) do
|
|
Delete(Args,1,1);
|
|
case Cmd of
|
|
'a','autocommit' :
|
|
FAutoCommit:=Not FAutoCommit;
|
|
'q','quit' :
|
|
begin
|
|
MaybeCommit;
|
|
Terminate;
|
|
end;
|
|
'x','exit' :
|
|
begin
|
|
MaybeRollBack;
|
|
Terminate;
|
|
end;
|
|
'c','commit' :
|
|
MaybeCommit;
|
|
'r','collback':
|
|
MaybeRollBack;
|
|
's',
|
|
'save' : SaveLast(Args);
|
|
'?','h','help' : WriteHelp;
|
|
end;
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.WriteHelp;
|
|
|
|
begin
|
|
Writeln('Commands : ');
|
|
Writeln('\a \autocommit Toggle autocommit (Current autocommit :',FAutoCommit,')');
|
|
Writeln('\c \commit commit');
|
|
Writeln('\h \help this help');
|
|
Writeln('\q \quit commit and quit');
|
|
Writeln('\r \rollback commit');
|
|
Writeln('\x \exit RollBack and quit');
|
|
Writeln('\s \save [FN] Save result of last select to XML file');
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.RunCommandLoop;
|
|
|
|
Var
|
|
S : UTF8String;
|
|
|
|
begin
|
|
Writeln('Enter commands, end with \q. \?, \h or \help for help.');
|
|
Repeat
|
|
Write('SQL > ');
|
|
Readln(S);
|
|
try
|
|
While (Length(S)>0) and (S[1] in CmdSep) do
|
|
Delete(S,1,1);
|
|
if Copy(S,1,1)='\' then
|
|
begin
|
|
Delete(S,1,1);
|
|
ExecuteSystemCommand(S)
|
|
end
|
|
else
|
|
ExecuteCommand(S)
|
|
except
|
|
On E : Exception do
|
|
Writeln(Format('Error %s executing command : %s',[E.ClassName,E.Message]));
|
|
end;
|
|
until Terminated;
|
|
Terminate;
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.Usage(Const Err : String);
|
|
|
|
Var
|
|
L : TStrings;
|
|
S : String;
|
|
|
|
begin
|
|
if (Err<>'') then
|
|
Writeln('Error : ',Err);
|
|
Writeln('Usage : ',ExtractFileName(Paramstr(0)),' [options]');
|
|
Writeln('Where options is one or more of:');
|
|
Writeln('-h --help This help text.');
|
|
Writeln('-t --type=TYPE Set connection type.');
|
|
Writeln('-d --database=DB Set database name.');
|
|
Writeln('-H --hostname=DB Set database hostname.');
|
|
Writeln('-u --username=NAME Set database user name.');
|
|
Writeln('-p --password=PWD Set database user password.');
|
|
Writeln('-c --charset=SET Set database character set.');
|
|
Writeln('-P --port=N Set database connection port.');
|
|
Writeln('Known connection types for this binary:');
|
|
L:=TStringList.Create;
|
|
try
|
|
GetConnectionList(L);
|
|
for S in L do
|
|
Writeln(' ',S);
|
|
finally
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
Function TSQLShellApplication.ParseArgs : Boolean;
|
|
|
|
Var
|
|
S : String;
|
|
|
|
begin
|
|
Result:=False;
|
|
S:=CheckOptions('hH:d:t:u:p:c:P:',['help','hostname:','database:','type:','username:','password:','c:charset','port']);
|
|
if (S<>'') or (HasOption('h','help')) then
|
|
begin
|
|
Usage(S);
|
|
exit;
|
|
end;
|
|
FConnType:=GetOptionValue('t','type');
|
|
FHostName:=GetOptionValue('H','hostname');
|
|
FDatabaseName:=GetOptionValue('d','database');
|
|
FUserName:=GetOptionValue('u','user');
|
|
FPassword:=GetOptionValue('p','password');
|
|
FCharset:=GetOptionValue('c','charset');
|
|
if HasOption('P','port') then
|
|
begin
|
|
FPort:=StrToIntDef(GetOptionValue('P','port'),-1);
|
|
if FPort=-1 then
|
|
Usage('Databasename not supplied');
|
|
exit;
|
|
end;
|
|
Result:=(FDatabaseName<>'');
|
|
if not Result then
|
|
Usage('Databasename not supplied');
|
|
end;
|
|
|
|
Procedure TSQLShellApplication.DoRun;
|
|
|
|
begin
|
|
StopOnException:=True;
|
|
if Not ParseArgs then
|
|
begin
|
|
terminate;
|
|
exit;
|
|
end;
|
|
ConnectToDatabase;
|
|
RunCommandLoop;
|
|
DisconnectFromDatabase;
|
|
end;
|
|
|
|
begin
|
|
With TSQLShellApplication.Create(Nil) do
|
|
try
|
|
Initialize;
|
|
Run;
|
|
finally
|
|
Free;
|
|
end;
|
|
end.
|
|
|
|
|