ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/examples/fbsql/fbsql.lpr
Revision: 45
Committed: Tue Dec 6 10:33:46 2016 UTC (7 years, 4 months ago) by tony
File size: 9669 byte(s)
Log Message:
Committing updates for Release R2-0-0

File Contents

# User Rev Content
1 tony 37 (*
2     * IBX For Lazarus (Firebird Express)
3     *
4     * The contents of this file are subject to the Initial Developer's
5     * Public License Version 1.0 (the "License"); you may not use this
6     * file except in compliance with the License. You may obtain a copy
7     * of the License here:
8     *
9     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10     *
11     * Software distributed under the License is distributed on an "AS
12     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13     * implied. See the License for the specific language governing rights
14     * and limitations under the License.
15     *
16     * The Initial Developer of the Original Code is Tony Whyman.
17     *
18     * The Original Code is (C) 2014 Tony Whyman, MWA Software
19     * (http://www.mwasoftware.co.uk).
20     *
21     * All Rights Reserved.
22     *
23     * Contributor(s): ______________________________________.
24     *
25     *)
26     program fbsql;
27    
28     {$mode objfpc}{$H+}
29    
30     uses
31     {$IFDEF UNIX}{$IFDEF UseCThreads}
32     cthreads,
33     {$ENDIF}{$ENDIF}
34     Classes, SysUtils, CustApp
35     { you can add units after this }
36     ,IBDatabase, ibxscript, IBExtract, IBQuery, DB;
37    
38     resourcestring
39    
40     sUnknownField = 'Unknown Field Type';
41     sBadGraphic = 'Unable to generate CSV data for a Graphic Field';
42     sBadParadox = 'Unable to generate CSV data for a Paradox OLE Field';
43     sBadDBase = 'Unable to generate CSV data for a DBase OLE Field';
44     sBadBinary = 'Unable to generate CSV data for a Binary Field';
45     sBadCursor = 'Unable to generate CSV data for a Cursor Field';
46    
47     type
48    
49     { TFBSQL }
50    
51     TFBSQL = class(TCustomApplication)
52     private
53     FIBDatabase: TIBDatabase;
54     FIBTransaction: TIBTransaction;
55     FIBXScript: TIBXScript;
56     FExtract: TIBExtract;
57     FQuery: TIBQuery;
58     FSQL: TStringStream;
59     procedure LogHandler(Sender: TObject; Msg: string);
60     procedure ErrorLogHandler(Sender: TObject; Msg: string);
61     procedure HandleSelectSQL(Sender: TObject; SQLText: string);
62     procedure WriteCSV;
63     protected
64     procedure DoRun; override;
65     procedure ShowException(E: Exception); override;
66     public
67     constructor Create(TheOwner: TComponent); override;
68     destructor Destroy; override;
69     procedure WriteHelp; virtual;
70     end;
71    
72     { TFBSQL }
73    
74     procedure TFBSQL.LogHandler(Sender: TObject; Msg: string);
75     begin
76     writeln( Msg);
77     end;
78    
79     procedure TFBSQL.ErrorLogHandler(Sender: TObject; Msg: string);
80     begin
81     writeln(stderr, Msg);
82     end;
83    
84     procedure TFBSQL.HandleSelectSQL(Sender: TObject; SQLText: string);
85     begin
86     FQuery.SQL.Text := SQLText;
87     FQuery.Active := true;
88     try
89     WriteCSV;
90     finally
91     FQuery.Active := false;
92     end;
93     end;
94    
95     procedure TFBSQL.WriteCSV;
96    
97     procedure WriteQuotedText(Text: string);
98     var Index: integer;
99     begin
100     Index := 1;
101     while Index <= Length(Text) do
102     if Text[Index] = '"' then
103     begin
104     Insert('"',Text,Index);
105     Inc(Index,2)
106     end
107     else
108     Inc(Index,1);
109     write('"' + Text + '"')
110     end;
111    
112     procedure WriteFieldList(Fields: TFields);
113     var I: integer;
114     begin
115     for I := 0 to Fields.Count - 1 do
116     begin
117     if I > 0 then write(',');
118     write(Fields[I].FieldName)
119     end;
120     writeln;
121     end;
122    
123     procedure WriteRecord;
124     var I: integer;
125     begin
126     with FQuery do
127     begin
128     for I := 0 to FieldCount - 1 do
129     begin
130     if I <> 0 then write(',');
131     case Fields[I].DataType of
132     ftUnknown: raise Exception.Create(sUnknownField);
133     ftString: WriteQuotedText(Fields[I].AsString);
134     ftSmallint,
135     ftInteger,
136     ftWord,
137     ftLargeInt,
138     ftBoolean: write(Fields[I].DisplayText);
139     ftFloat,
140     ftCurrency,
141     ftFmtBCD,
142     ftBCD: write(Fields[I].AsString);
143     ftDate,
144     ftTime: write(DateTimeToStr(Fields[I].AsDateTime));
145     ftDateTime: WriteQuotedText(Fields[I].AsString);
146     ftBytes,
147     ftVarBytes,
148     ftBlob,
149     ftAutoInc: write(Fields[I].AsString);
150     ftMemo: WriteQuotedText(Fields[I].AsString);
151     ftGraphic: raise Exception.Create(sBadGraphic);
152     ftFmtMemo: WriteQuotedText(Fields[I].AsString);
153     ftParadoxOle: raise Exception.Create(sBadParadox);
154     ftDBaseOle: raise Exception.Create(sBadDBase);
155     ftTypedBinary:raise Exception.Create(sBadBinary);
156     ftCursor: raise Exception.Create(sBadCursor);
157     end
158     end;
159     writeln;
160     end;
161     end;
162     begin
163     with FQuery do
164     begin
165     WriteFieldList(Fields);
166     First;
167     while not EOF do
168     begin
169     WriteRecord;
170     Next
171     end;
172     end
173     end;
174    
175     procedure TFBSQL.DoRun;
176     var
177     ErrorMsg: String;
178     SQLFileName: string;
179     DoExtract: boolean;
180     i: integer;
181     begin
182     writeln(stderr,'fbsql: a non-interactive SQL interpreter for Firebird');
183     writeln(stderr,'Copyright (c) MWA Software 2016');
184     // quick check parameters
185     ErrorMsg:=CheckOptions('ahbeufprs',['help','user','pass','role']);
186     if ErrorMsg<>'' then begin
187     ShowException(Exception.Create(ErrorMsg));
188     Terminate;
189     Exit;
190     end;
191    
192     // parse parameters
193     if HasOption('h','help') or (ParamCount = 0) then
194     begin
195     WriteHelp;
196     Terminate;
197     Exit;
198     end;
199    
200     SQLFileName := '';
201     DoExtract := false;
202    
203     {Initialise user_name and password from environment if available}
204    
205     if GetEnvironmentVariable('ISC_USER') <> '' then
206     FIBDatabase.Params.Add('user_name=' + GetEnvironmentVariable('ISC_USER'));
207    
208     if GetEnvironmentVariable('ISC_PASSWORD') <> '' then
209     FIBDatabase.Params.Add('password=' + GetEnvironmentVariable('ISC_PASSWORD'));
210    
211     {Process Command line options}
212    
213     if HasOption('u','user') then
214     FIBDatabase.Params.Add('user_name=' + GetOptionValue('u','user'));
215    
216     if HasOption('p','pass') then
217     FIBDatabase.Params.Add('password=' + GetOptionValue('p','pass'));
218    
219     if HasOption('r','role') then
220     FIBDatabase.Params.Add('sql_role_name=' + GetOptionValue('r','role'));
221    
222     if (ParamCount >= 1) and (ParamStr(ParamCount)[1] <> '-') then
223     FIBDatabase.DatabaseName := ParamStr(ParamCount)
224     else
225     raise Exception.Create('Database Name Missing');
226    
227     if not HasOption('b') then
228     FIBXScript.StopOnFirstError := false;
229    
230     if not HasOption('e') then
231     FIBXScript.Echo := false;
232    
233     if HasOption('a') then
234     DoExtract := true;
235    
236     if HasOption('f') then
237     SQLFileName := GetOptionValue('f');
238    
239     if HasOption('s') then
240     begin
241     FSQL.WriteString(GetOptionValue('s'));
242     FSQL.Position := 0;
243     end;
244    
245     {Validation}
246    
247     if not DoExtract then
248     begin
249     if (SQLFileName = '') and (FSQL.DataString = '') then
250     raise Exception.Create('An SQL File must be provided');
251    
252     if (FSQL.DataString <> '') and (SQLFileName <> '') then
253     raise Exception.Create('An SQL Script File and text cannot be simulateously requested');
254    
255     if (FSQL.DataString = '') and not FileExists(SQLFileName) then
256     raise Exception.CreateFmt('SQL File "%s" not found!',[SQLFileName]);
257    
258     end;
259    
260     if DoExtract and ((SQLFileName <> '') or (FSQL.DataString <> '')) then
261     raise Exception.Create('Extract and script execution cannot be simulateously requested');
262    
263     {This is where it all happens}
264    
265     FIBDatabase.Connected := true;
266     try
267     if DoExtract then
268     begin
269     FExtract.ExtractObject(eoDatabase);
270     for i := 0 to FExtract.Items.Count - 1 do
271     writeln(FExtract.Items[i]);
272     end
273     else
274     if FSQL.DataString = '' then
275     FIBXScript.PerformUpdate(SQLFileName,true)
276     else
277     FIBXScript.PerformUpdate(FSQL,true);
278     finally
279     FIBDatabase.Connected := false;
280     end;
281    
282    
283     // stop program loop
284     Terminate;
285     end;
286    
287     procedure TFBSQL.ShowException(E: Exception);
288     begin
289     writeln(stderr,'Error: ' + E.Message);
290     end;
291    
292     constructor TFBSQL.Create(TheOwner: TComponent);
293     begin
294     inherited Create(TheOwner);
295     StopOnException:=True;
296     FSQL := TStringStream.Create('');
297    
298     { Create Components }
299     FIBDatabase := TIBDatabase.Create(self);
300     FIBTransaction := TIBTransaction.Create(self);
301     FIBTransaction.DefaultDatabase := FIBDatabase;
302     FIBXScript := TIBXScript.Create(self);
303     FIBXScript.Database := FIBDatabase;
304     FIBXScript.Transaction := FIBTransaction;
305     FIBXScript.OnOutputLog := @LogHandler;
306     FIBXScript.OnErrorLog := @ErrorLogHandler;
307     FIBXScript.OnSelectSQL := @HandleSelectSQL;
308     FExtract := TIBExtract.Create(self);
309     FExtract.Database := FIBDatabase;
310     FExtract.Transaction := FIBTransaction;
311     FQuery := TIBQuery.Create(self);
312 tony 45 FQuery.AllowAutoActivateTransaction := true;
313 tony 37 FQuery.Database := FIBDatabase;
314     FQuery.Transaction := FIBTransaction;
315    
316     FIBTransaction.Params.Add('concurrency');
317     FIBTransaction.Params.Add('wait');
318     FIBDatabase.Params.Add('lc_ctype=UTF8');
319    
320     end;
321    
322     destructor TFBSQL.Destroy;
323     begin
324     if assigned(FSQL) then FSQL.Free;
325     inherited Destroy;
326     end;
327    
328     procedure TFBSQL.WriteHelp;
329     begin
330     writeln(stderr,'Usage: ',ExtractFileName(ExeName),' <options> <database name>');
331     writeln(stderr,'Options:');
332     writeln(stderr,'-a write database metadata to stdout');
333     writeln(stderr,'-b stop on first error');
334     writeln(stderr,'-e echo sql statements to stdout');
335     writeln(stderr,'-f <filename> execute SQL script from file');
336     writeln(stderr,'-h show this information');
337     writeln(stderr,'-p <password> provide password on command line (insecure)');
338     writeln(stderr,'-r <rolename> open database with this rolename');
339     writeln(stderr,'-s <sql> Execute SQL text');
340     writeln(stderr,'-u <username> open database with this username (defaults to SYSDBA)');
341     writeln;
342     writeln(stderr,'Environment Variables:');
343     writeln(stderr,'ISC_USER Login user Name');
344     writeln(stderr,'ISC_PASSWORD Login password');
345     end;
346    
347     var
348     Application: TFBSQL;
349     begin
350     Application:=TFBSQL.Create(nil);
351     Application.Title:='fbsql';
352     Application.Run;
353     Application.Free;
354     end.
355