1 unit TestSQLDB;
2
3 {
4 Unit tests which are specific to the sqlDB components like TSQLQuery, TSQLConnection.
5 }
6
7 {$mode objfpc}{$H+}
8
9 interface
10
11 uses
12 Classes, sqldb, SysUtils, fpcunit, testregistry,
13 sqldbtoolsunit,toolsunit, db;
14
15 type
16
17 { TSQLDBTestCase }
18
19 TSQLDBTestCase = class(TTestCase)
20 private
GetSQLDBConnectornull21 function GetSQLDBConnector: TSQLDBConnector;
22 protected
23 procedure SetUp; override;
24 procedure TearDown; override;
25 Property SQLDBConnector : TSQLDBConnector Read GetSQLDBConnector;
26 end;
27
28 { TTestTSQLQuery }
29
30 TTestTSQLQuery = class(TSQLDBTestCase)
31 private
32 FMyQ: TSQLQuery;
33 FPrepareCount:Integer;
34 procedure DoAfterPost(DataSet: TDataSet);
35 Procedure DoApplyUpdates;
36 procedure DoCount(Sender: TSQLConnection; EventType: TDBEventType; const Msg: String);
37 Procedure TrySetQueryOptions;
38 Procedure TrySetPacketRecords;
39 Protected
40 Procedure Setup; override;
41 published
42 procedure TestMasterDetail;
43 procedure TestUpdateServerIndexDefs;
44 Procedure TestKeepOpenOnCommit;
45 Procedure TestKeepOpenOnCommitPacketRecords;
46 Procedure TestCheckSettingsOnlyWhenInactive;
47 Procedure TestAutoApplyUpdatesPost;
48 Procedure TestAutoApplyUpdatesDelete;
49 Procedure TestCheckRowsAffected;
50 Procedure TestAutoCommit;
51 Procedure TestGeneratedRefreshSQL;
52 Procedure TestGeneratedRefreshSQL1Field;
53 Procedure TestGeneratedRefreshSQLNoKey;
54 Procedure TestRefreshSQL;
55 Procedure TestRefreshSQLMultipleRecords;
56 Procedure TestRefreshSQLNoRecords;
57 Procedure TestFetchAutoInc;
58 procedure TestSequence;
59 procedure TestReturningInsert;
60 procedure TestReturningUpdate;
61 procedure TestMacros;
62 Procedure TestPrepareCount;
63 Procedure TestNullTypeParam;
64 end;
65
66 { TTestTSQLConnection }
67
68 TTestTSQLConnection = class(TSQLDBTestCase)
69 private
70 procedure SetImplicit;
71 procedure TestImplicitTransaction;
72 procedure TestImplicitTransaction2;
73 procedure TestImplicitTransactionNotAssignable;
74 procedure TestImplicitTransactionOK;
75 procedure TryOpen;
76 published
77 procedure TestUseImplicitTransaction;
78 procedure TestUseExplicitTransaction;
79 procedure TestExplicitConnect;
80 procedure TestGetStatementInfo;
81 procedure TestGetNextValue;
82 end;
83
84 { TTestTSQLScript }
85
86 TTestTSQLScript = class(TSQLDBTestCase)
87 published
88 procedure TestExecuteScript;
89 procedure TestScriptColon; //bug 25334
90 procedure TestUseCommit; //E.g. Firebird cannot use COMMIT RETAIN if mixing DDL and DML in a script
91 end;
92
93 implementation
94
95
96
97 { TTestTSQLQuery }
98
99 procedure TTestTSQLQuery.Setup;
100 begin
101 inherited Setup;
102 FPrepareCount:=0;
103 SQLDBConnector.Connection.Options:=[];
104 end;
105
106 procedure TTestTSQLQuery.TestMasterDetail;
107 var MasterQuery, DetailQuery: TSQLQuery;
108 MasterSource: TDataSource;
109 begin
110 with SQLDBConnector do
111 try
112 MasterQuery := GetNDataset(10) as TSQLQuery;
113 MasterSource := TDatasource.Create(nil);
114 MasterSource.DataSet := MasterQuery;
115 DetailQuery := Query;
116 DetailQuery.SQL.Text := 'select NAME from FPDEV where ID=:ID';
117 DetailQuery.DataSource := MasterSource;
118
119 MasterQuery.Open;
120 DetailQuery.Open;
121 CheckEquals('TestName1', DetailQuery.Fields[0].AsString);
122 MasterQuery.MoveBy(3);
123 CheckEquals('TestName4', DetailQuery.Fields[0].AsString);
124
125 MasterQuery.Close;
126 CheckTrue(DetailQuery.Active, 'Detail dataset should remain intact, when master dataset is closed');
127 finally
128 MasterSource.Free;
129 end;
130 end;
131
132 procedure TTestTSQLQuery.TestUpdateServerIndexDefs;
133 var Q: TSQLQuery;
134 name1, name2, name3: string;
135 begin
136 // Test retrieval of information about indexes on unquoted and quoted table names
137 // (tests also case-sensitivity for DB's that support case-sensitivity of quoted identifiers)
138 // For ODBC Firebird/Interbase we must define primary key as named constraint and
139 // in ODBC driver must be set: "quoted identifiers" and "sensitive identifier"
140 // See also: TTestFieldTypes.TestUpdateIndexDefs
141 with SQLDBConnector do
142 begin
143 // SQLite ignores case-sensitivity of quoted table names
144 // MS SQL Server case-sensitivity of identifiers depends on the case-sensitivity of default collation of the database
145 // MySQL case-sensitivity depends on case-sensitivity of server's file system
146 if SQLServerType in [ssMSSQL,ssSQLite{$IFDEF WINDOWS},ssMySQL{$ENDIF}] then
147 name1 := Connection.FieldNameQuoteChars[0]+'fpdev 2'+Connection.FieldNameQuoteChars[1]
148 else
149 name1 := 'FPDEV2';
150 ExecuteDirect('create table '+name1+' (id integer not null, constraint PK_FPDEV21 primary key(id))');
151 // same but quoted table name
152 name2 := Connection.FieldNameQuoteChars[0]+'FPdev2'+Connection.FieldNameQuoteChars[1];
153 ExecuteDirect('create table '+name2+' (ID2 integer not null, constraint PK_FPDEV22 primary key(ID2))');
154 // embedded quote in table name
155 if SQLServerType in [ssMySQL] then
156 name3 := '`FPdev``2`'
157 else
158 name3 := Connection.FieldNameQuoteChars[0]+'FPdev""2'+Connection.FieldNameQuoteChars[1];
159 ExecuteDirect('create table '+name3+' (Id3 integer not null, constraint PK_FPDEV23 primary key(Id3))');
160 CommitDDL;
161 end;
162
163 try
164 Q := SQLDBConnector.Query;
165 Q.SQL.Text:='select * from '+name1;
166 Q.Prepare;
167 Q.ServerIndexDefs.Update;
168 CheckEquals(1, Q.ServerIndexDefs.Count);
169
170 Q.SQL.Text:='select * from '+name2;
171 Q.Prepare;
172 Q.ServerIndexDefs.Update;
173 CheckEquals(1, Q.ServerIndexDefs.Count, '2.1');
174 CheckTrue(CompareText('ID2', Q.ServerIndexDefs[0].Fields)=0, '2.2'+Q.ServerIndexDefs[0].Fields);
175 CheckTrue(Q.ServerIndexDefs[0].Options=[ixPrimary,ixUnique], '2.3');
176
177 Q.SQL.Text:='select * from '+name3;
178 Q.Prepare;
179 Q.ServerIndexDefs.Update;
180 CheckEquals(1, Q.ServerIndexDefs.Count, '3.1');
181 CheckTrue(CompareText('ID3', Q.ServerIndexDefs[0].Fields)=0, '3.2');
182 CheckTrue(Q.ServerIndexDefs[0].Options=[ixPrimary,ixUnique], '3.3');
183 finally
184 Q.UnPrepare;
185 with SQLDBConnector do
186 begin
187 ExecuteDirect('DROP TABLE '+name1);
188 ExecuteDirect('DROP TABLE '+name2);
189 ExecuteDirect('DROP TABLE '+name3);
190 CommitDDL;
191 end;
192 end;
193 end;
194
195 procedure TTestTSQLQuery.TestKeepOpenOnCommit;
196 var Q: TSQLQuery;
197 I: Integer;
198 begin
199 // Test that for a SQL query with Options=sqoKeepOpenOnCommit, calling commit does not close the dataset.
200 // Test also that an edit still works.
201 with SQLDBConnector do
202 begin
203 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
204 Transaction.Commit;
205 for I:=1 to 20 do
206 ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
207 Transaction.Commit;
208
209 Q := SQLDBConnector.Query;
210 Q.SQL.Text:='select * from FPDEV2';
211 Q.Options:=[sqoKeepOpenOnCommit,sqoRefreshUsingSelect];
212 AssertEquals('PacketRecords forced to -1',-1,Q.PacketRecords);
213 Q.Open;
214 AssertEquals('Got all records',20,Q.RecordCount);
215 Q.SQLTransaction.Commit;
216 AssertTrue('Still open after transaction',Q.Active);
217
218 // Now check editing
219 Q.Locate('id',20,[]);
220 Q.Edit;
221 Q.FieldByName('a').AsString:='abc';
222 Q.Post;
223 AssertTrue('Have updates pending',Q.UpdateStatus=usModified);
224 Q.ApplyUpdates;
225 AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
226 Q.Close;
227 Q.SQL.Text:='select * from FPDEV2 where (id=20) and (a=''abc'')';
228 Q.Open;
229 AssertTrue('Have modified data record in database', not (Q.EOF AND Q.BOF));
230 end;
231 end;
232
233 procedure TTestTSQLQuery.TrySetPacketRecords;
234 begin
235 FMyQ.PacketRecords:=10;
236 end;
237
238 procedure TTestTSQLQuery.TestKeepOpenOnCommitPacketRecords;
239 begin
240 with SQLDBConnector do
241 begin
242 FMyQ := SQLDBConnector.Query;
243 FMyQ.Options:=[sqoKeepOpenOnCommit];
244 AssertException('Cannot set PacketRecords when sqoKeepOpenOnCommit is active',EDatabaseError,@TrySetPacketRecords);
245 end;
246 end;
247
248 procedure TTestTSQLQuery.TrySetQueryOptions;
249 begin
250 FMyQ.Options:=[sqoKeepOpenOnCommit];
251 end;
252
253 procedure TTestTSQLQuery.TestCheckSettingsOnlyWhenInactive;
254 begin
255 // Check that we can only set QueryOptions when the query is inactive.
256 with SQLDBConnector do
257 begin
258 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
259 Transaction.Commit;
260 ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[1,1]));
261 Transaction.Commit;
262 FMyQ := SQLDBConnector.Query;
263 FMyQ.SQL.Text:='select * from FPDEV2';
264 FMyQ := SQLDBConnector.Query;
265 FMyQ.Open;
266 AssertException('Cannot set Options when query is active',EDatabaseError,@TrySetQueryOptions);
267 end;
268 end;
269
270 procedure TTestTSQLQuery.DoAfterPost(DataSet: TDataSet);
271 begin
272 AssertTrue('Have modifications in after post',FMyq.UpdateStatus=usModified)
273 end;
274
275 procedure TTestTSQLQuery.TestAutoApplyUpdatesPost;
276 var Q: TSQLQuery;
277 I: Integer;
278 begin
279 // Test that if sqoAutoApplyUpdates is in QueryOptions, then POST automatically does an ApplyUpdates
280 // Test also that POST afterpost event is backwards compatible.
281 with SQLDBConnector do
282 begin
283 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
284 Transaction.COmmit;
285 for I:=1 to 2 do
286 ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
287 Transaction.COmmit;
288 Q := SQLDBConnector.Query;
289 FMyQ:=Q; // so th event handler can reach it.
290 Q.SQL.Text:='select * from FPDEV2';
291 Q.Options:=[sqoAutoApplyUpdates];
292 // We must test that in AfterPost, the modification is still there, for backwards compatibilty
293 Q.AfterPost:=@DoAfterPost;
294 Q.Open;
295 AssertEquals('Got all records',2,Q.RecordCount);
296 // Now check editing
297 Q.Locate('id',2,[]);
298 Q.Edit;
299 Q.FieldByName('a').AsString:='abc';
300 Q.Post;
301 AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
302 Q.Close;
303 Q.SQL.Text:='select * from FPDEV2 where (id=2) and (a=''abc'')';
304 Q.Open;
305 AssertTrue('Have modified data record in database',not (Q.EOF AND Q.BOF));
306 end;
307
308 end;
309
310 procedure TTestTSQLQuery.TestAutoApplyUpdatesDelete;
311
312 var Q: TSQLQuery;
313 I: Integer;
314 begin
315 // Test that if sqoAutoApplyUpdates is in QueryOptions, then Delete automatically does an ApplyUpdates
316 with SQLDBConnector do
317 begin
318 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
319 Transaction.COmmit;
320 for I:=1 to 2 do
321 ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
322 Transaction.COmmit;
323 Q := SQLDBConnector.Query;
324 FMyQ:=Q; // so th event handler can reach it.
325 Q.SQL.Text:='select * from FPDEV2';
326 Q.Options:=[sqoAutoApplyUpdates];
327 // We must test that in AfterPost, the modification is still there, for backwards compatibilty
328 Q.AfterPost:=@DoAfterPost;
329 Q.Open;
330 AssertEquals('Got all records',2,Q.RecordCount);
331 // Now check editing
332 Q.Locate('id',2,[]);
333 Q.Delete;
334 AssertTrue('Have no more updates pending',Q.UpdateStatus=usUnmodified);
335 Q.Close;
336 Q.SQL.Text:='select * from FPDEV2 where (id=2)';
337 Q.Open;
338 AssertTrue('Data record is deleted in database', (Q.EOF AND Q.BOF));
339 end;
340 end;
341
342 procedure TTestTSQLQuery.DoApplyUpdates;
343
344 begin
345 FMyQ.ApplyUpdates();
346 end;
347
348 procedure TTestTSQLQuery.DoCount(Sender: TSQLConnection; EventType: TDBEventType; const Msg: String);
349 begin
350 If (EventType=detPrepare) then
351 Inc(FPrepareCount);
352 end;
353
354 procedure TTestTSQLQuery.TestCheckRowsAffected;
355 var Q: TSQLQuery;
356 I: Integer;
357 begin
358 // Test that if sqoAutoApplyUpdates is in QueryOptions, then Delete automatically does an ApplyUpdates
359 with SQLDBConnector do
360 begin
361 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
362 Transaction.COmmit;
363 for I:=1 to 2 do
364 ExecuteDirect(Format('INSERT INTO FPDEV2 values (%d,''%.6d'')',[i,i]));
365 Transaction.COmmit;
366 SQLDBConnector.Connection.Options:=[scoApplyUpdatesChecksRowsAffected];
367 Q := SQLDBConnector.Query;
368 Q.SQL.Text:='select * from FPDEV2';
369 Q.DeleteSQL.Text:='delete from FPDEV2';
370 Q.Open;
371 AssertEquals('Got all records',2,Q.RecordCount);
372 // Now check editing
373 Q.Delete;
374 FMyQ:=Q;
375 AssertException('RowsAffected > 1 raises exception',EUpdateError,@DoApplyUpdates);
376 end;
377 end;
378
379 procedure TTestTSQLQuery.TestAutoCommit;
380 var
381 I : Integer;
382 begin
383 with SQLDBConnector do
384 begin
385 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
386 if Transaction.Active then
387 Transaction.Commit;
388
389 Query.Options:=[sqoAutoCommit];
390 for I:=1 to 2 do
391 begin
392 Query.SQL.Text:=Format('INSERT INTO FPDEV2 values (%d,''%.6d'');',[i,i]);
393 Query.Prepare;
394 Query.ExecSQL;
395 // We do not commit anything explicitly.
396 end;
397
398 AssertFalse('Transaction is still active after expected auto commit', Transaction.Active);
399
400 Connection.Close;
401 Connection.Open;
402
403 Query.SQL.Text:='SELECT COUNT(*) from FPDEV2';
404 Query.Open;
405 AssertEquals('Records haven''t been committed to database', 2, Query.Fields[0].AsInteger);
406 end;
407 end;
408
409 procedure TTestTSQLQuery.TestGeneratedRefreshSQL;
410
411 var
412 Q: TSQLQuery;
413
414 begin
415 with SQLDBConnector do
416 begin
417 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
418 if Transaction.Active then
419 Transaction.Commit;
420 end;
421 Q:=SQLDBConnector.Query;
422 Q.SQL.Text:='select * from FPDEV2';
423 Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
424 Q.Options:=Q.Options+[sqoRefreshUsingSelect];
425 Q.Open;
426 With Q.FieldByName('id') do
427 ProviderFlags:=ProviderFlags+[pfInKey];
428 With Q.FieldByName('a') do
429 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
430 With Q.FieldByName('b') do
431 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
432 Q.Insert;
433 Q.FieldByName('id').AsInteger:=1;
434 Q.Post;
435 AssertTrue('Field value has not been fetched after post',Q.FieldByName('a').IsNull);
436 Q.ApplyUpdates(0);
437 AssertEquals('Still on correct field',1,Q.FieldByName('id').AsInteger);
438 AssertEquals('Field value has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
439 AssertEquals('Field value has been fetched from the database ','fgh',Q.FieldByName('b').AsString);
440 end;
441
442 procedure TTestTSQLQuery.TestGeneratedRefreshSQL1Field;
443 var
444 Q: TSQLQuery;
445
446 begin
447 with SQLDBConnector do
448 begin
449 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
450 if Transaction.Active then
451 Transaction.Commit;
452 end;
453 Q:=SQLDBConnector.Query;
454 Q.SQL.Text:='select * from FPDEV2';
455 Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
456 Q.Options:=Q.Options+[sqoRefreshUsingSelect];
457 Q.Open;
458 With Q.FieldByName('id') do
459 ProviderFlags:=ProviderFlags+[pfInKey];
460 With Q.FieldByName('a') do
461 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
462 Q.Insert;
463 Q.FieldByName('id').AsInteger:=1;
464 Q.Post;
465 AssertTrue('Field value has not been fetched after post',Q.FieldByName('a').IsNull);
466 Q.ApplyUpdates(0);
467 AssertEquals('Still on correct field',1,Q.FieldByName('id').AsInteger);
468 AssertEquals('Field value a has been fetched from the database ','abcde',Q.FieldByName('a').AsString);
469 AssertEquals('Field value b has NOT been fetched from the database ','',Q.FieldByName('b').AsString);
470 end;
471
472 procedure TTestTSQLQuery.TestGeneratedRefreshSQLNoKey;
473 begin
474 with SQLDBConnector do
475 begin
476 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
477 if Transaction.Active then
478 Transaction.Commit;
479 end;
480 FMyQ:=SQLDBConnector.Query;
481 FMyQ.SQL.Text:='select * from FPDEV2';
482 FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
483 FMyQ.Options:=FMyQ.Options+[sqoRefreshUsingSelect];
484 FMyQ.Open;
485 With FMyQ.FieldByName('id') do
486 ProviderFlags:=ProviderFlags-[pfInKey];
487 With FMyQ.FieldByName('a') do
488 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
489 FMyQ.Insert;
490 FMyQ.FieldByName('id').AsInteger:=1;
491 FMyQ.Post;
492 AssertException('Cannot refresh without primary key',EUpdateError,@DoApplyUpdates);
493 end;
494
495 procedure TTestTSQLQuery.TestRefreshSQL;
496 var
497 Q: TSQLQuery;
498
499 begin
500 with SQLDBConnector do
501 begin
502 ExecuteDirect('create table FPDEV2 (id integer not null primary key, a varchar(5) default ''abcde'', b integer default 1)');
503 if Transaction.Active then
504 Transaction.Commit;
505 end;
506 Q:=SQLDBConnector.Query;
507 Q.SQL.Text:='select * from FPDEV2';
508 Q.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
509 Q.RefreshSQL.Text:='SELECT a,b FROM FPDEV2 WHERE (id=:id)';
510 Q.Open;
511 Q.Insert; // #1 record
512 Q.FieldByName('id').AsInteger:=1;
513 Q.Post;
514 Q.Append; // #2 record
515 Q.FieldByName('id').AsInteger:=2;
516 Q.Post;
517 AssertTrue('Field value has not been fetched after Post', Q.FieldByName('a').IsNull);
518 Q.ApplyUpdates(0);
519 // #2 record:
520 AssertEquals('Still on correct field', 2, Q.FieldByName('id').AsInteger);
521 AssertEquals('Field value has been fetched from the database', 'abcde', Q.FieldByName('a').AsString);
522 AssertEquals('Field value has been fetched from the database', 1, Q.FieldByName('b').AsInteger);
523 Q.Prior;
524 // #1 record:
525 AssertEquals('Still on correct field', 1, Q.FieldByName('id').AsInteger);
526 AssertEquals('Field value has been fetched from the database', 'abcde', Q.FieldByName('a').AsString);
527 AssertEquals('Field value has been fetched from the database', 1, Q.FieldByName('b').AsInteger);
528 end;
529
530 procedure TTestTSQLQuery.TestRefreshSQLMultipleRecords;
531
532 begin
533 with SQLDBConnector do
534 begin
535 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
536 if Transaction.Active then
537 Transaction.Commit;
538 ExecuteDirect('insert into FPDEV2 (id) values (123)');
539 if Transaction.Active then
540 Transaction.Commit;
541 end;
542 FMyQ:=SQLDBConnector.Query;
543 FMyQ.SQL.Text:='select * from FPDEV2';
544 FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
545 FMyQ.RefreshSQL.Text:='select * from FPDEV2';
546 FMyQ.Open;
547 With FMyQ.FieldByName('id') do
548 ProviderFlags:=ProviderFlags+[pfInKey];
549 With FMyQ.FieldByName('a') do
550 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
551 FMyQ.Insert;
552 FMyQ.FieldByName('id').AsInteger:=1;
553 FMyQ.Post;
554 AssertException('Multiple records returned by RefreshSQL gives an error',EUpdateError,@DoApplyUpdates);
555 end;
556
557 procedure TTestTSQLQuery.TestRefreshSQLNoRecords;
558 begin
559 with SQLDBConnector do
560 begin
561 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
562 if Transaction.Active then
563 Transaction.Commit;
564 ExecuteDirect('insert into FPDEV2 (id) values (123)');
565 if Transaction.Active then
566 Transaction.Commit;
567 end;
568 FMyQ:=SQLDBConnector.Query;
569 FMyQ.SQL.Text:='select * from FPDEV2';
570 FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
571 FMyQ.RefreshSQL.Text:='select * from FPDEV2 where 1=2';
572 FMyQ.Open;
573 With FMyQ.FieldByName('id') do
574 ProviderFlags:=ProviderFlags+[pfInKey];
575 With FMyQ.FieldByName('a') do
576 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert,pfRefreshOnUpdate];
577 FMyQ.Insert;
578 FMyQ.FieldByName('id').AsInteger:=1;
579 FMyQ.Post;
580 AssertException('No records returned by RefreshSQL gives an error',EUpdateError,@DoApplyUpdates);
581 end;
582
583 procedure TTestTSQLQuery.TestFetchAutoInc;
584 var datatype: string;
585 id: largeint;
586 begin
587 with SQLDBConnector do
588 begin
589 case SQLServerType of
590 ssMySQL:
591 datatype := 'integer auto_increment';
592 ssMSSQL, ssSybase:
593 datatype := 'integer identity';
594 ssSQLite:
595 datatype := 'integer';
596 else
597 Ignore(STestNotApplicable);
598 end;
599 ExecuteDirect('create table FPDEV2 (id '+datatype+' primary key, f varchar(5))');
600 CommitDDL;
601 end;
602
603 with SQLDBConnector.Query do
604 begin
605 SQL.Text:='select * from FPDEV2';
606 Open;
607 Insert;
608 FieldByName('f').AsString:='a';
609 Post; // #1 record
610 Append;
611 FieldByName('f').AsString:='b';
612 Post; // #2 record
613 AssertTrue('ID field is not null after Post', FieldByName('id').IsNull);
614 First; // #1 record
615 ApplyUpdates(0);
616 AssertTrue('ID field is still null after ApplyUpdates', Not FieldByName('id').IsNull);
617 // Should be 1 after the table was created, but this is not guaranteed... So we just test positive values.
618 id := FieldByName('id').AsLargeInt;
619 AssertTrue('ID field has not positive value', id>0);
620 Next; // #2 record
621 AssertTrue('Next ID value is not greater than previous', FieldByName('id').AsLargeInt>id);
622 end;
623 end;
624
625 procedure TTestTSQLQuery.TestSequence;
626 var SequenceNames : TStringList;
627 begin
628 case SQLServerType of
629 ssFirebird:
630 SQLDBConnector.ExecuteDirect('create sequence FPDEV_SEQ1');
631 ssMSSQL, ssOracle, ssPostgreSQL:
632 SQLDBConnector.ExecuteDirect('create sequence FPDEV_SEQ1 MINVALUE 1');
633 else
634 Ignore(STestNotApplicable);
635 end;
636 SQLDBConnector.ExecuteDirect('create table FPDEV2 (id integer)');
637 SQLDBConnector.CommitDDL;
638
639 with SQLDBConnector.Query do
640 begin
641 SQL.Text := 'select * from FPDEV2';
642 Sequence.FieldName:='id';
643 Sequence.SequenceName:='FPDEV_SEQ1';
644 Open;
645 // default is get next value on new record
646 Append;
647 AssertEquals(1, FieldByName('id').AsInteger);
648
649 Sequence.ApplyEvent:=saeOnPost;
650 Append;
651 AssertTrue('Field ID must be null after Append', FieldByName('id').IsNull);
652 Post;
653 AssertEquals(2, FieldByName('id').AsInteger);
654 end;
655
656 // test GetSequenceNames
657 SequenceNames := TStringList.Create;
658 try
659 SQLDBConnector.Connection.GetSequenceNames(SequenceNames);
660 AssertTrue(SequenceNames.IndexOf('FPDEV_SEQ1') >= 0);
661 finally
662 SequenceNames.Free;
663 end;
664
665 SQLDBConnector.ExecuteDirect('drop sequence FPDEV_SEQ1');
666 SQLDBConnector.CommitDDL;
667 end;
668
669 procedure TTestTSQLQuery.TestReturningInsert;
670
671 begin
672 with SQLDBConnector do
673 begin
674 if not (sqSupportReturning in Connection.ConnOptions) then
675 Ignore(STestNotApplicable);
676 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
677 if Transaction.Active then
678 Transaction.Commit;
679 ExecuteDirect('insert into FPDEV2 (id) values (123)');
680 if Transaction.Active then
681 Transaction.Commit;
682 end;
683 FMyQ:=SQLDBConnector.Query;
684 FMyQ.SQL.Text:='select * from FPDEV2';
685 // FMyQ.InsertSQL.Text:='insert into FPDEV2 (id) values (:id)';
686 FMyQ.Open;
687 With FMyQ.FieldByName('id') do
688 ProviderFlags:=ProviderFlags+[pfInKey];
689 With FMyQ.FieldByName('a') do
690 ProviderFlags:=ProviderFlags+[pfRefreshOnInsert];
691 With FMyQ.FieldByName('b') do
692 ProviderFlags:=[];
693 FMyQ.Insert;
694 FMyQ.FieldByName('id').AsInteger:=1;
695 FMyQ.Post;
696 FMyQ.ApplyUpdates;
697 AssertEquals('a updated','abcde',FMyQ.FieldByName('a').AsString);
698 AssertEquals('b not updated','',FMyQ.FieldByName('b').AsString);
699 end;
700
701 procedure TTestTSQLQuery.TestReturningUpdate;
702
703 begin
704 with SQLDBConnector do
705 begin
706 if not (sqSupportReturning in Connection.ConnOptions) then
707 Ignore(STestNotApplicable);
708 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10) default ''abcde'', b varchar(5) default ''fgh'', constraint PK_FPDEV2 primary key(id))');
709 CommitDDL;
710 ExecuteDirect('insert into FPDEV2 (id) values (1)');
711 ExecuteDirect('insert into FPDEV2 (id) values (2)');
712 end;
713 FMyQ:=SQLDBConnector.Query;
714 FMyQ.SQL.Text:='select * from FPDEV2';
715 FMyQ.Open;
716 With FMyQ.FieldByName('id') do
717 ProviderFlags:=ProviderFlags+[pfInKey];
718 With FMyQ.FieldByName('b') do
719 ProviderFlags:=[pfRefreshOnUpdate]; // Do not update, just fetch new value
720 SQLDBConnector.ExecuteDirect('update FPDEV2 set b=''b1'' where id=1');
721 SQLDBConnector.ExecuteDirect('update FPDEV2 set b=''b2'' where id=2');
722 FMyQ.Edit;
723 FMyQ.FieldByName('a').AsString:='a1';
724 FMyQ.Post; // #1 record
725 FMyQ.Next;
726 FMyQ.Edit;
727 FMyQ.FieldByName('a').AsString:='a2';
728 FMyQ.Post; // #2 record
729 FMyQ.ApplyUpdates;
730 FMyQ.First;
731 AssertEquals('#1.a updated', 'a1', FMyQ.FieldByName('a').AsString);
732 AssertEquals('#1.b updated', 'b1', FMyQ.FieldByName('b').AsString);
733 FMyQ.Next;
734 AssertEquals('#2.a updated', 'a2', FMyQ.FieldByName('a').AsString);
735 AssertEquals('#2.b updated', 'b2', FMyQ.FieldByName('b').AsString);
736 end;
737
738 procedure TTestTSQLQuery.TestMacros;
739 begin
740 with SQLDBConnector do
741 begin
742 ExecuteDirect('create table FPDEV2 (id integer not null, constraint PK_FPDEV2 primary key(id))');
743 CommitDDL;
744 ExecuteDirect('insert into FPDEV2 (id) values (1)');
745 ExecuteDirect('insert into FPDEV2 (id) values (2)');
746 end;
747
748 With SQLDBConnector.Query do
749 begin
750 SQL.Text:='Select ID from FPDEV2 '+
751 '%WHERE_CL' +sLineBreak+
752 '%ORDER_CL' +sLineBreak;
753 MacroCheck:=true;
754 MacroByName('WHERE_CL').AsString:='where 1=1';
755 MacroByName('ORDER_CL').AsString:='order by 1';
756 Open;
757 AssertEquals('Correct SQL executed, macros substituted: ',1,Fields[0].AsInteger);
758 Close;
759 MacroByName('ORDER_CL').AsString := 'Order by 1 DESC';
760 Open;
761 AssertEquals('Correct SQL executed, macro value changed: ',2,Fields[0].AsInteger);
762 end;
763 end;
764
765 procedure TTestTSQLQuery.TestPrepareCount;
766
767 begin
768 with SQLDBConnector do
769 begin
770 ExecuteDirect('create table FPDEV2 (id integer not null, constraint PK_FPDEV2 primary key(id))');
771 CommitDDL;
772 ExecuteDirect('insert into FPDEV2 (id) values (1)');
773 ExecuteDirect('insert into FPDEV2 (id) values (2)');
774 Connection.OnLog:=@DoCount;
775 Connection.LogEvents:=[detPrepare];
776 end;
777 try
778 With SQLDBConnector.Query do
779 begin
780 Unidirectional:=True; // Disable server index defs etc
781 UsePrimaryKeyAsKey:=False; // Idem
782 SQL.Text:='Select ID from FPDEV2 where (ID=:ID)';
783 ParamByname('ID').AsInteger:=1;
784 Prepare;
785 Open;
786 AssertEquals('Correct record count param 1',1,RecordCount);
787 AssertEquals('Correct SQL executed, correct paramete: ',1,Fields[0].AsInteger);
788 Close;
789 ParamByname('ID').AsInteger:=2;
790 Open;
791 AssertEquals('Correct record count param 2',1,RecordCount);
792 AssertEquals('Correct SQL executed, macro value changed: ',2,Fields[0].AsInteger);
793 end;
794 AssertEquals('Prepare called only once ',1,FPrepareCount);
795 finally
796 SQLDBConnector.Connection.OnLog:=Nil;
797 end;
798
799 end;
800
801 procedure TTestTSQLQuery.TestNullTypeParam;
802 begin
803 if not (SQLServerType in [ssSQLite, ssFirebird]) then
804 Ignore(STestNotApplicable);
805 CreateAndFillIDField;
806 try
807 With SQLDBConnector.Query do
808 begin
809 UsePrimaryKeyAsKey:=False; // Disable server index defs etc
810 SQL.Text:='Select ID from FPDEV2 where (:ID IS NULL or ID = :ID)';
811 Open;
812 AssertEquals('Correct record count param NULL',10,RecordCount);
813 Close;
814 ParamByname('ID').AsInteger:=1;
815 Open;
816 AssertEquals('Correct record count param 1',1,RecordCount);
817 AssertEquals('Correct field value: ',1,Fields[0].AsInteger);
818 Close;
819 end;
820 finally
821 SQLDBConnector.Connection.OnLog:=Nil;
822 end;
823 end;
824
825
826 { TTestTSQLConnection }
827
828 procedure TTestTSQLConnection.TestImplicitTransaction;
829
830 Var
831 T : TSQLTransaction;
832
833 begin
834 T:=TSQLTransaction.Create(Nil);
835 try
836 T.Options:=[stoUseImplicit];
837 T.DataBase:=SQLDBConnector.Connection;
838 finally
839 T.Free;
840 end;
841 end;
842
843 procedure TTestTSQLConnection.TestImplicitTransaction2;
844
845 Var
846 T : TSQLTransaction;
847
848 begin
849 T:=TSQLTransaction.Create(Nil);
850 try
851 T.Options:=[stoUseImplicit];
852 SQLDBConnector.Connection.Transaction:=T;
853 finally
854 T.Free;
855 end;
856 end;
857
858 procedure TTestTSQLConnection.SetImplicit;
859
860 begin
861 SQLDBConnector.Transaction.Options:=[stoUseImplicit];
862 end;
863
864 procedure TTestTSQLConnection.TestImplicitTransactionNotAssignable;
865
866 begin
867 AssertException('Cannot set toUseImplicit option if database does not allow it',EDatabaseError,@SetImplicit);
868 AssertException('Cannot assign database to transaction with toUseImplicit, if database does not allow it',EDatabaseError,@TestImplicitTransaction);
869 AssertException('Cannot assign transaction with toUseImplicit to database, if database does not allow it',EDatabaseError,@TestImplicitTransaction2);
870 end;
871
872 procedure TTestTSQLConnection.TestImplicitTransactionOK;
873
874 var
875 Q : TSQLQuery;
876 T : TSQLTransaction;
877 I : Integer;
878 begin
879 with SQLDBConnector do
880 begin
881 ExecuteDirect('create table FPDEV2 (id integer not null, a varchar(10), constraint PK_FPDEV2 primary key(id))');
882 if Transaction.Active then
883 Transaction.Commit;
884 end;
885 SetImplicit;
886 Q:=SQLDBConnector.Query;
887 for I:=1 to 2 do
888 begin
889 Q.SQL.Text:=Format('INSERT INTO FPDEV2 values (%d,''%.6d'');',[i,i]);
890 Q.Prepare;
891 Q.ExecSQL;
892 // We do not commit anything explicitly.
893 end;
894 Q:=Nil;
895 T:=Nil;
896 try
897 T:=TSQLTransaction.Create(Nil);
898 Q:=TSQLQuery.Create(Nil);
899 Q.Transaction:=T;
900 Q.Database:=SQLDBConnector.Connection;
901 T.Database:=SQLDBConnector.Connection;
902 Q.SQL.text:='SELECT COUNT(*) from FPDEV2';
903 Q.Open;
904 AssertEquals('Records have been committed to database',2,Q.Fields[0].AsInteger);
905 finally
906 Q.Free;
907 T.Free;
908 end;
909 end;
910
911 procedure TTestTSQLConnection.TestUseImplicitTransaction;
912 begin
913 if (sqImplicitTransaction in SQLDBConnector.Connection.ConnOptions) then
914 TestImplicitTransactionOK
915 else
916 TestImplicitTransactionNotAssignable;
917 end;
918
919 procedure TTestTSQLConnection.TryOpen;
920
921 begin
922 SQLDBConnector.Query.Open;
923 end;
924
925 procedure TTestTSQLConnection.TestUseExplicitTransaction;
926 begin
927 SQLDBConnector.Transaction.Active:=False;
928 SQLDBConnector.Transaction.Options:=[stoExplicitStart];
929 SQLDBConnector.Query.SQL.Text:='select * from FPDEV';
930 AssertException('toExplicitStart raises exception on implicit start',EDatabaseError,@TryOpen)
931 end;
932
933 procedure TTestTSQLConnection.TestExplicitConnect;
934 begin
935 SQLDBConnector.Transaction.Active:=False;
936 SQLDBConnector.Connection.Options:=[scoExplicitConnect];
937 SQLDBConnector.Connection.Connected:=False;
938 SQLDBConnector.Query.SQL.Text:='select * from FPDEV';
939 AssertException('toExplicitStart raises exception on implicit start',EDatabaseError,@TryOpen)
940 end;
941
942 procedure TTestTSQLConnection.TestGetStatementInfo;
943 var StmtInfo: TSQLStatementInfo;
944 begin
945 // single table
946 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM tab1');
947 AssertEquals('StatementType', ord(stSELECT), ord(StmtInfo.StatementType));
948 AssertEquals('TableName', 'tab1', StmtInfo.TableName);
949 AssertEquals('Updateable', True, StmtInfo.Updateable);
950 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM tab2 WHERE col1=1');
951 AssertEquals('TableName', 'tab2', StmtInfo.TableName);
952 AssertEquals('Updateable', True, StmtInfo.Updateable);
953 // single table with schema
954 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM dbo.tab2 WHERE col1=1');
955 AssertEquals('TableName', 'dbo.tab2', StmtInfo.TableName);
956 AssertEquals('Updateable', True, StmtInfo.Updateable);
957 // single table with quoted schema
958 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM "dbo".tab2 WHERE col1=1');
959 AssertEquals('TableName', '"dbo".tab2', StmtInfo.TableName);
960 AssertEquals('Updateable', True, StmtInfo.Updateable);
961 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM "dbo"."tab2" WHERE col1=1');
962 AssertEquals('TableName', '"dbo"."tab2"', StmtInfo.TableName);
963 AssertEquals('Updateable', True, StmtInfo.Updateable);
964 // multiple tables
965 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM tab3,tab4 WHERE col1=1');
966 AssertEquals('TableName', '', StmtInfo.TableName);
967 AssertEquals('Updateable', False, StmtInfo.Updateable);
968 // function
StmtInfonull969 StmtInfo := SQLDBConnector.Connection.GetStatementInfo('SELECT * FROM dbo.fn1(1)');
970 AssertEquals('TableName', '', StmtInfo.TableName);
971 AssertEquals('Updateable', False, StmtInfo.Updateable);
972 end;
973
974 procedure TTestTSQLConnection.TestGetNextValue;
975 begin
976 if not (sqSequences in SQLDBConnector.Connection.ConnOptions) then
977 Ignore('Connector '+SQLDBConnector.Connection.ClassName+' does not support sequences');
978 if SQLServerType=ssSQLite then
979 begin
980 SQLDBConnector.TryDropIfExist('me');
981 SQLDBConnector.ExecuteDirect('create table me (a integer primary key autoincrement,b int)');
982 SQLDBConnector.ExecuteDirect('insert into me (b) values (1)');// Will create table sqlite_sequence if it didn't exist yet
983 SQLDBConnector.ExecuteDirect('drop table me');
984 end;
985 SQLDBConnector.TryDropSequence('me');
986 SQLDBConnector.TryCreateSequence('me');
987 AssertTrue('Get value',SQLDBConnector.Connection.GetNextValue('me',1)>0);
988 end;
989
990
991 { TTestTSQLScript }
992
993 procedure TTestTSQLScript.TestExecuteScript;
994 var Ascript : TSQLScript;
995 begin
996 Ascript := TSQLScript.Create(nil);
997 try
998 with Ascript do
999 begin
1000 DataBase := SQLDBConnector.Connection;
1001 Transaction := SQLDBConnector.Transaction;
1002 Script.Clear;
1003 Script.Append('create table FPDEV_A (id int);');
1004 Script.Append('create table FPDEV_B (id int);');
1005 ExecuteScript;
1006 // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
1007 SQLDBConnector.CommitDDL;
1008 end;
1009 finally
1010 AScript.Free;
1011 SQLDBConnector.ExecuteDirect('drop table FPDEV_A');
1012 SQLDBConnector.ExecuteDirect('drop table FPDEV_B');
1013 // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
1014 SQLDBConnector.CommitDDL;
1015 end;
1016 end;
1017
1018 procedure TTestTSQLScript.TestScriptColon;
1019 // Bug 25334: TSQLScript incorrectly treats : in scripts as sqldb query parameter markers
1020 // Firebird-only test; can be extended for other dbs that use : in SQL
1021 var
1022 Ascript : TSQLScript;
1023 begin
1024 if not(SQLConnType in [interbase]) then Ignore(STestNotApplicable);
1025 Ascript := TSQLScript.Create(nil);
1026 try
1027 with Ascript do
1028 begin
1029 DataBase := SQLDBConnector.Connection;
1030 Transaction := SQLDBConnector.Transaction;
1031 Script.Clear;
1032 UseSetTerm := true;
1033 // Example procedure that selects table names
1034 Script.Append(
1035 'SET TERM ^ ; '+LineEnding+
1036 'CREATE PROCEDURE FPDEV_TESTCOLON '+LineEnding+
1037 'RETURNS (tblname VARCHAR(31)) '+LineEnding+
1038 'AS '+LineEnding+
1039 'begin '+LineEnding+
1040 '/* Show tables. Note statement uses colon */ '+LineEnding+
1041 'FOR '+LineEnding+
1042 ' SELECT RDB$RELATION_NAME '+LineEnding+
1043 ' FROM RDB$RELATIONS '+LineEnding+
1044 ' ORDER BY RDB$RELATION_NAME '+LineEnding+
1045 ' INTO :tblname '+LineEnding+
1046 'DO '+LineEnding+
1047 ' SUSPEND; '+LineEnding+
1048 'end^ '+LineEnding+
1049 'SET TERM ; ^'
1050 );
1051 ExecuteScript;
1052 // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
1053 SQLDBConnector.CommitDDL;
1054 end;
1055 finally
1056 AScript.Free;
1057 SQLDBConnector.ExecuteDirect('DROP PROCEDURE FPDEV_TESTCOLON');
1058 // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
1059 SQLDBConnector.CommitDDL;
1060 end;
1061 end;
1062
1063 procedure TTestTSQLScript.TestUseCommit;
1064 // E.g. Firebird needs explicit COMMIT sometimes, e.g. if mixing DDL and DML
1065 // statements in a script.
1066 // Probably same as bug 17829 Error executing SQL script
1067 const
1068 TestValue='Some text';
1069 var
1070 Ascript : TSQLScript;
1071 CheckQuery : TSQLQuery;
1072 begin
1073 Ascript := TSQLScript.Create(nil);
1074 try
1075 with Ascript do
1076 begin
1077 DataBase := SQLDBConnector.Connection;
1078 Transaction := SQLDBConnector.Transaction;
1079 Script.Clear;
1080 UseCommit:=true;
1081 // Example procedure that selects table names
1082 Script.Append('CREATE TABLE fpdev_scriptusecommit (logmessage VARCHAR(255));');
1083 Script.Append('COMMIT;'); //needed for table to show up
1084 Script.Append('INSERT INTO fpdev_scriptusecommit (logmessage) VALUES('''+TestValue+''');');
1085 Script.Append('COMMIT;');
1086 ExecuteScript;
1087 // This line should not run, as the commit above should have taken care of it:
1088 //SQLDBConnector.CommitDDL;
1089 // Test whether second line of script executed, just to be sure
1090 CheckQuery:=SQLDBConnector.Query;
1091 CheckQuery.SQL.Text:='SELECT logmessage FROM fpdev_scriptusecommit ';
1092 CheckQuery.Open;
1093 CheckEquals(TestValue, CheckQuery.Fields[0].AsString, 'Insert script line should have inserted '+TestValue);
1094 CheckQuery.Close;
1095 end;
1096 finally
1097 AScript.Free;
1098 SQLDBConnector.ExecuteDirect('DROP TABLE fpdev_scriptusecommit');
1099 SQLDBConnector.Transaction.Commit;
1100 end;
1101 end;
1102
1103 { TSQLDBTestCase }
1104
GetSQLDBConnectornull1105 function TSQLDBTestCase.GetSQLDBConnector: TSQLDBConnector;
1106 begin
1107 Result := DBConnector as TSQLDBConnector;
1108 end;
1109
1110 procedure TSQLDBTestCase.SetUp;
1111 begin
1112 inherited SetUp;
1113 InitialiseDBConnector;
1114 DBConnector.StartTest(TestName);
1115 end;
1116
1117 procedure TSQLDBTestCase.TearDown;
1118 begin
1119 DBConnector.StopTest(TestName);
1120 if assigned(DBConnector) then
1121 with SQLDBConnector do
1122 if Assigned(Transaction) and Transaction.Active and not (stoUseImplicit in Transaction.Options) then
1123 Transaction.Rollback;
1124 FreeDBConnector;
1125 inherited TearDown;
1126 end;
1127
1128
1129 initialization
1130 if uppercase(dbconnectorname)='SQL' then
1131 begin
1132 RegisterTest(TTestTSQLQuery);
1133 RegisterTest(TTestTSQLConnection);
1134 RegisterTest(TTestTSQLScript);
1135 end;
1136 end.
1137