File: mainform.pas

package info (click to toggle)
lazarus 2.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 214,460 kB
  • sloc: pascal: 1,862,622; xml: 265,709; cpp: 56,595; sh: 3,008; java: 609; makefile: 535; perl: 297; sql: 222; ansic: 137
file content (269 lines) | stat: -rw-r--r-- 10,751 bytes parent folder | download | duplicates (4)
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
unit mainform;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Dialogs, StdCtrls,
  dbconfiggui, dbconfig,
  {General db unit}sqldb,
  {For EDataBaseError}db,
  {Now we add all databases we want to support, otherwise their drivers won't be loaded}
  {$IFNDEF Solaris}IBConnection,{$ENDIF}pqconnection,sqlite3conn,
  mssqlconn,mysql50conn,mysql51conn,mysql55conn,odbcconn,oracleconnection,
  sqlscript {the unit that contains tsqlscript};

type

  { TForm1 }

  TForm1 = class(TForm)
    CmdCopyDDL: TButton;
    CmdOpenSQL: TButton;
    CmdCopyDML: TButton;
    CmdRunScript: TButton;
    OpenDialog1: TOpenDialog;
    ScriptMemo: TMemo;
    procedure CmdCopyDDLClick(Sender: TObject);
    procedure CmdCopyDMLClick(Sender: TObject);
    procedure CmdOpenSQLClick(Sender: TObject);
    procedure CmdRunScriptClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FConn: TSQLConnector;
    FQuery: TSQLQuery;
    FTran: TSQLTransaction;
    // Run database connection test when asked
    function ConnectionTest(ChosenConfig: TDBConnectionConfig): boolean;
    // Display script error to the user
    procedure ShowScriptException(Sender: TObject; Statement: TStrings; TheException: Exception; var Continue: boolean);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  LoginForm: TDBConfigForm;
begin
  FConn:=TSQLConnector.Create(nil);
  FQuery:=TSQLQuery.Create(nil);
  FTran:=TSQLTransaction.Create(nil);
  FConn.Transaction:=FTran;
  FQuery.DataBase:=FConn;

  LoginForm:=TDBConfigForm.Create(self);
  try
    // The test button on dbconfiggui will link to this procedure:
    LoginForm.ConnectionTestCallback:=@ConnectionTest;
    LoginForm.ConnectorType.Clear; //remove any default connectors
    // Now add the dbs that you support - use the name of the *ConnectionDef.TypeName property
    {$IFNDEF Solaris}
    // Not available on Solaris
    LoginForm.ConnectorType.AddItem('Firebird', nil);
    {$ENDIF}
    LoginForm.ConnectorType.AddItem('MSSQLServer', nil);
    LoginForm.ConnectorType.AddItem('MySQL50', nil);
    LoginForm.ConnectorType.AddItem('MySQL51', nil);
    LoginForm.ConnectorType.AddItem('MySQL55', nil);
    LoginForm.ConnectorType.AddItem('ODBC', nil);
    LoginForm.ConnectorType.AddItem('Oracle', nil);
    LoginForm.ConnectorType.AddItem('PostGreSQL', nil);
    LoginForm.ConnectorType.AddItem('SQLite3', nil);
    LoginForm.ConnectorType.AddItem('Sybase', nil);
    case LoginForm.ShowModal of
    mrOK:
      begin
        // User wants to connect, so copy over db info
        FConn.ConnectorType:=LoginForm.Config.DBType;
        FConn.HostName:=LoginForm.Config.DBHost;
        FConn.DatabaseName:=LoginForm.Config.DBPath;
        FConn.UserName:=LoginForm.Config.DBUser;
        FConn.Password:=LoginForm.Config.DBPassword;
        FConn.Transaction:=FTran;
      end;
    mrCancel:
      begin
        ShowMessage('You canceled the database login. Application will terminate.');
        Application.Terminate;
      end;
    end;
  finally
    LoginForm.Free;
  end;
  // Get a script before the user's eyes:
  CmdCopyDDLClick(nil);
end;

procedure TForm1.CmdCopyDDLClick(Sender: TObject);
// Script that sets up tables as used in SQLdb_Tutorial1..3
// Also includes a photo blob used in the LazReport tutorial
// Notice we include 2 SQL statements, each terminated with ;
const ScriptText=
  'CREATE TABLE CUSTOMER '+LineEnding+
  '( '+LineEnding+
  '  CUST_NO INTEGER NOT NULL, '+LineEnding+
  '  CUSTOMER VARCHAR(25) NOT NULL, '+LineEnding+
  '  CITY VARCHAR(25), '+LineEnding+
  '  COUNTRY VARCHAR(15), '+LineEnding+
  '  CONSTRAINT CT_CUSTOMER_PK PRIMARY KEY (CUST_NO) '+LineEnding+
  '); '+LineEnding+
  'CREATE TABLE EMPLOYEE '+LineEnding+
  '( '+LineEnding+
  '  EMP_NO INTEGER NOT NULL, '+LineEnding+
  '  FIRST_NAME VARCHAR(15) NOT NULL, '+LineEnding+
  '  LAST_NAME VARCHAR(20) NOT NULL, '+LineEnding+
  '  PHONE_EXT VARCHAR(4), '+LineEnding+
  '  JOB_CODE VARCHAR(5) NOT NULL, '+LineEnding+
  '  JOB_GRADE INTEGER NOT NULL, '+LineEnding+
  '  JOB_COUNTRY VARCHAR(15) NOT NULL, '+LineEnding+
  '  SALARY NUMERIC(10,2) NOT NULL, '+LineEnding+
  '  PHOTO BLOB SUB_TYPE BINARY, '+LineEnding+
  '  CONSTRAINT CT_EMPLOYEE_PK PRIMARY KEY (EMP_NO) '+LineEnding+
  ');';
begin
  Scriptmemo.Lines.Text:=ScriptText;
end;

procedure TForm1.CmdCopyDMLClick(Sender: TObject);
// Script that fills the table with sample data as used in SQLdb_Tutorial1..3
// The double quotes inside the statements will be parsed by the Pascal compiler and
// end up as single quotes in the actual ScriptText string, like SQL expects it.
const ScriptText=
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (1, ''Michael Design'', ''San Diego'', ''USA''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (2, ''VC Technologies'', ''Dallas'', ''USA''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (3, ''Klämpfl, Van Canneyt'', ''Boston'', ''USA''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (4, ''Felipe Bank'', ''Manchester'', ''England''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (5, ''Joost Systems, LTD.'', ''Central Hong Kong'', ''Hong Kong''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (6, ''Van der Voort Int.'', ''Ottawa'', ''Canada''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (7, ''Mrs. Mauvais'', ''Pebble Beach'', ''USA''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (8, ''Asinine Vacation Rentals'', ''Lihue'', ''USA''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (9, ''Fax'', ''Turtle Island'', ''Fiji''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (10, ''FPC Corporation'', ''Tokyo'', ''Japan''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (11, ''Dynamic Intelligence Corp'', ''Zurich'', ''Switzerland''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (12, ''3D-Pad Corp.'', ''Paris'', ''France''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (13, ''Swen Export, Ltd.'', ''Milan'', ''Italy''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (14, ''Graeme Consulting'', ''Brussels'', ''Belgium''); '+LineEnding+
  'INSERT INTO CUSTOMER (CUST_NO, CUSTOMER, CITY, COUNTRY) VALUES (15, ''Klenin Inc.'', ''Den Haag'', ''Netherlands''); '+LineEnding+
  'INSERT INTO employee(emp_no, first_name, last_name, phone_ext, job_code, job_grade,  '+LineEnding+
  '  job_country, salary) '+LineEnding+
  '  VALUES (1,''William'',''Shatner'',''1702'',''CEO'',1,''USA'',48000); '+LineEnding+
  'INSERT INTO employee(emp_no, first_name, last_name, phone_ext, job_code, job_grade,  '+LineEnding+
  '  job_country, salary) '+LineEnding+
  '  VALUES (2,''Ivan'',''Rzeszow'',''9802'',''Eng'',2,''Russia'',38000); '+LineEnding+
  'INSERT INTO employee(emp_no, first_name, last_name, phone_ext, job_code, job_grade,  '+LineEnding+
  '  job_country, salary) '+LineEnding+
  '  VALUES (3,''Erin'',''Powell'',''1703'',''Admin'',2,''USA'',45368); ';
begin
  Scriptmemo.Lines.Text:=ScriptText;
end;

procedure TForm1.CmdOpenSQLClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    ScriptMemo.Clear;
    ScriptMemo.Lines.LoadFromFile(OpenDialog1.FileName);
  end;
end;

procedure TForm1.CmdRunScriptClick(Sender: TObject);
// The heart of the program: runs the script in the memo
var
  OurScript: TSQLScript;
begin
  OurScript:=TSQLScript.Create(nil);
  try
    OurScript.Database:=FConn; //Indicate what db & ...
    OurScript.Transaction:=FTran; // ... transaction we actually want to run the script against
    OurScript.Script.Assign(ScriptMemo.Lines); //Copy over the script itself
    //Now set some options:
    OurScript.UseCommit:=true; //try process any COMMITs inside the script, instead of batching everything together. See readme.txt though
    //SET TERM is Firebird specific, used when creating stored procedures etc.
    if FConn.ConnectorType='Firebird' then
      OurScript.UseSetTerm:=true
    else
      OurScript.UseSetTerm:=false;
    OurScript.CommentsInSQL:=false; //Send commits to db server as well; could be useful to troubleshoot by monitoring all SQL statements at the server
    OurScript.OnException:=@ShowScriptException; //when errors occur, let this procedure handle the error display
    try
      if not(FTran.Active) then
        FTran.StartTransaction; //better safe than sorry
      OurScript.Execute;
      FTran.Commit; //Make sure entire script is committed to the db
      ShowMessage('Script was successfully run.');
    except
      on E: EDataBaseError do
      begin
        // Error was already displayed via ShowScriptException, so no need for this:
        //ShowMessage('Error running script: '+E.Message);
        FTran.Rollback;
      end;
    end;
  finally
    OurScript.Free;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FQuery.Free;
  FTran.Free;
  FConn.Free;
end;

function TForm1.ConnectionTest(ChosenConfig: TDBConnectionConfig): boolean;
// Callback function that uses the info in dbconfiggui to test a connection
// and return the result of the test to dbconfiggui
var
  // Generic database connector...
  Conn: TSQLConnector;
begin
  result:=false;
  Conn:=TSQLConnector.Create(nil);
  Screen.Cursor:=crHourglass;
  try
    // ...actual connector type is determined by this property.
    // Make sure the ChosenConfig.DBType string matches
    // the connectortype (e.g. see the string in the
    // T*ConnectionDef.TypeName for that connector .
    Conn.ConnectorType:=ChosenConfig.DBType;
    Conn.HostName:=ChosenConfig.DBHost;
    Conn.DatabaseName:=ChosenConfig.DBPath;
    Conn.UserName:=ChosenConfig.DBUser;
    Conn.Password:=ChosenConfig.DBPassword;
    try
      Conn.Open;
      result:=Conn.Connected;
    except
      // Result is already false
    end;
    Conn.Close;
  finally
    Screen.Cursor:=crDefault;
    Conn.Free;
  end;
end;

procedure TForm1.ShowScriptException(Sender: TObject; Statement: TStrings;
  TheException: Exception; var Continue: boolean);
begin
  // Shows script execution error to user
  // todo: should really be a separate form with a memo big enough to display a large statement
  ShowMessage('Script error: '+TheException.Message+LineEnding+
    Statement.Text);
  Continue:=false; //indicate script should stop
end;

end.