testbasics.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. unit TestBasics;
  2. {$IFDEF FPC}
  3. {$mode objfpc}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. fpcunit, testregistry,
  8. Classes, SysUtils, db;
  9. type
  10. { TTestBasics }
  11. TTestBasics = class(TTestCase)
  12. private
  13. function CreateDatasetWith3Fields: TDataset;
  14. protected
  15. published
  16. procedure TestParseSQL;
  17. procedure TestInitFielddefsFromFields;
  18. procedure TestDoubleFieldDef;
  19. procedure TestFieldDefWithoutDS;
  20. procedure TestGetParamList;
  21. procedure TestGetFieldList;
  22. procedure TestExtractFieldName; //move record then copy. Is copy identical? Has record position changed?
  23. procedure TestCheckFieldNames;
  24. procedure TestFindField;
  25. end;
  26. implementation
  27. uses toolsunit;
  28. Type
  29. HackedDataset = class(TDataset);
  30. { TMyDataset }
  31. TMyDataset = Class(TDataset)
  32. protected
  33. function GetRecord(Buffer: TRecordBuffer; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
  34. procedure InternalClose; override;
  35. procedure InternalInitFieldDefs; override;
  36. procedure InternalOpen; override;
  37. function IsCursorOpen: Boolean; override;
  38. end;
  39. { TMyDataset }
  40. function TMyDataset.GetRecord(Buffer: TRecordBuffer; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
  41. begin
  42. Result:=grOK;
  43. Raise ENotImplemented.Create('GetRecord not implemented');
  44. end;
  45. procedure TMyDataset.InternalClose;
  46. begin
  47. Raise ENotImplemented.Create('Internalclose not implemented');
  48. end;
  49. procedure TMyDataset.InternalInitFieldDefs;
  50. begin
  51. Raise ENotImplemented.Create('InternalInitFieldDefs not implemented');
  52. end;
  53. procedure TMyDataset.InternalOpen;
  54. begin
  55. Raise ENotImplemented.Create('InternalOpen not implemented');
  56. end;
  57. function TMyDataset.IsCursorOpen: Boolean;
  58. begin
  59. Result:=False;
  60. Raise ENotImplemented.Create('IsCursorOpen not implemented');
  61. end;
  62. { TTestBasics }
  63. function TTestBasics.CreateDatasetWith3Fields: TDataset;
  64. var
  65. F: TField;
  66. begin
  67. Result := TMyDataset.Create(nil);
  68. F := TIntegerField.Create(Result);
  69. F.FieldName := 'Field1';
  70. F.DataSet := Result;
  71. F := TIntegerField.Create(Result);
  72. F.FieldName := 'Field2';
  73. F.DataSet := Result;
  74. F := TIntegerField.Create(Result);
  75. F.FieldName := 'Field3';
  76. F.DataSet := Result;
  77. end;
  78. procedure TTestBasics.TestParseSQL;
  79. var Params : TParams;
  80. ReplStr : string;
  81. pb : TParamBinding;
  82. i : integer;
  83. SQLStr : string;
  84. begin
  85. Params := TParams.Create;
  86. AssertEquals( 'select * from table where id = $1',
  87. params.ParseSQL('select * from table where id = :id',true,True,True,psPostgreSQL));
  88. AssertEquals( 'select * from table where id = $1',
  89. params.ParseSQL('select * from table where id = :id',false,True,True,psPostgreSQL));
  90. AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $2)',
  91. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,True,True,psPostgreSQL));
  92. AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $3) and (test=''$test'')',
  93. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,true,true,psPostgreSQL));
  94. AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 10=$10 11=$11 12=$5 where (id = $3) and (test=''$test'')',
  95. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,true,true,psPostgreSQL));
  96. AssertEquals( 'select * from table where id = $1',
  97. params.ParseSQL('select * from table where id = :id',true,true,false,psSimulated,pb,ReplStr));
  98. AssertEquals('$',ReplStr);
  99. AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $2)',
  100. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,true,false,psSimulated,pb,ReplStr));
  101. AssertEquals('$',ReplStr);
  102. AssertEquals( 'update test set 1=$$1 2=$$2 3=$$3 4=$$4 5=$$5 6=$$6 7=$$7 8=$$8 9=$$9 where (id = $$3) and (test=''$test'')',
  103. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,true,false,psSimulated,pb,ReplStr));
  104. AssertEquals('$$',ReplStr);
  105. AssertEquals( 'update test set 1=$$1 2=$$2 3=$$3 4=$$4 5=$$5 6=$$6 7=$$7 8=$$8 9=$$9 10=$$10 11=$$11 12=$$5 where (id = $$3) and (test=''$test'')',
  106. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,True,True,psSimulated));
  107. AssertEquals('$$',ReplStr);
  108. AssertEquals( 'update test set 1=$$$1 2=$$$2 3=$$$3 4=$$$4 5=$$$5 6=$$$6 7=$$$7 8=$$$8 9=$$$9 10=$$$10 11=$$$11 12=$$$5 where (id$$ = $$$3) and (test$=''$test'')',
  109. params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id$$ = :par3) and (test$=''$test'')',true,true,False,psSimulated,pb,ReplStr));
  110. AssertEquals('$$$',ReplStr);
  111. AssertEquals( 'select * from table where id = ?',
  112. params.ParseSQL('select * from table where id = :id',true,true,true,psInterbase));
  113. // Test bug 10345
  114. AssertEquals( 'select email from table where upper(email) like ''%''||?||''%''',
  115. params.ParseSQL('select email from table where upper(email) like ''%''||:email||''%''',true,true,true,psInterbase));
  116. // Test escape-sequences:
  117. AssertEquals( 'select * from table where ''id '''' = :id''',
  118. params.ParseSQL('select * from table where ''id '''' = :id''',true,False,True,psPostgreSQL));
  119. AssertEquals( 'select * from table where "id "" = :id"',
  120. params.ParseSQL('select * from table where "id "" = :id"',true,False,True,psPostgreSQL));
  121. AssertEquals( 'select * from table where "id \" = :id"',
  122. params.ParseSQL('select * from table where "id \" = :id"',true,True,False,psPostgreSQL));
  123. AssertEquals( 'select * from table where "id \" = $1',
  124. params.ParseSQL('select * from table where "id \" = :id',true,False,False,psPostgreSQL));
  125. AssertEquals( 'select * from table where "id = :id\',
  126. params.ParseSQL('select * from table where "id = :id\',true,True,True,psInterbase));
  127. // Test strange-field names
  128. AssertEquals( 'select * from table where "field-name" = ?',
  129. params.ParseSQL('select * from table where "field-name" = :"field-name"',true,True,True,psInterbase));
  130. AssertEquals('field-name',Params.Items[0].Name);
  131. AssertEquals( 'select * from table where "field-name" = ?',
  132. params.ParseSQL('select * from table where "field-name" = :"field-name',true,True,True,psInterbase));
  133. // Test more than 99 params - bug 19645
  134. SQLStr := 'update test set';
  135. for i := 1 to 101 do
  136. SQLStr := format('%s field%d=:par%d', [SQLStr,i,i]);
  137. AssertEquals( StringReplace(SQLStr, ':par', '$', [rfReplaceAll]),
  138. Params.ParseSQL(SQLStr, True, True, True, psPostgreSQL) );
  139. // Test comments:
  140. // Simple comment
  141. AssertEquals( 'select * from table where id= --comment :c'#10'$1-$2 or id= --:c'#13'-$3',
  142. Params.ParseSQL('select * from table where id= --comment :c'#10':a-:b or id= --:c'#13'-:d', True, True, True, psPostgreSQL));
  143. // Bracketed comment
  144. AssertEquals( 'select * from table where id=/*comment :c*/$1-$2',
  145. Params.ParseSQL('select * from table where id=/*comment :c*/:a-:b', True, True, True, psPostgreSQL));
  146. AssertEquals( 'select * from table where id=/*comment :c**/$1-$2',
  147. Params.ParseSQL('select * from table where id=/*comment :c**/:a-:b', True, True, True, psPostgreSQL));
  148. // Consecutive comments, with quote in second comment
  149. AssertEquals( '--c1'#10'--c'''#10'select '':a'' from table where id=$1',
  150. Params.ParseSQL('--c1'#10'--c'''#10'select '':a'' from table where id=:id', True, True, True, psPostgreSQL));
  151. Params.Free;
  152. end;
  153. procedure TTestBasics.TestInitFielddefsFromFields;
  154. var ds : TDataset;
  155. F1,F2,F3 : Tfield;
  156. Procedure CompareFieldAndFieldDef(Fld: TField; FldDef : TFieldDef);
  157. begin
  158. AssertEquals(Fld.FieldName,FldDef.Name);
  159. AssertEquals(Fld.Size,FldDef.Size);
  160. AssertEquals(Fld.Required,FldDef.Required);
  161. AssertTrue(Fld.DataType=FldDef.DataType);
  162. end;
  163. begin
  164. ds := TMyDataset.Create(nil);
  165. try
  166. F1:=TStringField.Create(ds);
  167. F1.Size := 10;
  168. F1.Name := 'StringFld';
  169. F1.FieldName := 'FStringFld';
  170. F1.Required := false;
  171. F1.Dataset:=ds;
  172. F2:=TIntegerField.Create(ds);
  173. F2.Name := 'IntegerFld';
  174. F2.FieldName := 'FIntegerFld';
  175. F2.Required := True;
  176. F2.Dataset:=ds;
  177. F3:=TBCDField.Create(ds);
  178. F3.Name := 'BCDFld';
  179. F3.FieldName := 'FBCDFld';
  180. F3.Required := false;
  181. F3.Dataset:=ds;
  182. (f3 as TBCDField).Precision := 2;
  183. HackedDataset(ds).InitFieldDefsFromfields;
  184. AssertEquals(3,ds.FieldDefs.Count);
  185. CompareFieldAndFieldDef(F1,ds.FieldDefs[0]);
  186. CompareFieldAndFieldDef(F2,ds.FieldDefs[1]);
  187. CompareFieldAndFieldDef(F3,ds.FieldDefs[2]);
  188. finally
  189. ds.Free;
  190. end;
  191. end;
  192. procedure TTestBasics.TestDoubleFieldDef;
  193. var ds : TDataset;
  194. PassException : boolean;
  195. begin
  196. // If a second field with the same name is added to a TFieldDefs, an exception
  197. // should occur
  198. ds := TMyDataset.Create(nil);
  199. try
  200. ds.FieldDefs.Add('Field1',ftInteger);
  201. PassException:=False;
  202. try
  203. ds.FieldDefs.Add('Field1',ftString,10,false)
  204. except
  205. on E: EDatabaseError do PassException := True;
  206. end;
  207. AssertTrue(PassException);
  208. finally
  209. ds.Free;
  210. end;
  211. end;
  212. procedure TTestBasics.TestFieldDefWithoutDS;
  213. var FieldDefs : TFieldDefs;
  214. begin
  215. FieldDefs := TFieldDefs.Create(nil);
  216. try
  217. FieldDefs.Add('test',ftString);
  218. finally
  219. FieldDefs.Free;
  220. end;
  221. end;
  222. procedure TTestBasics.TestGetFieldList;
  223. var
  224. ds: TDataSet;
  225. List: TList;
  226. ExceptionRaised: Boolean;
  227. begin
  228. ds := CreateDatasetWith3Fields;
  229. try
  230. List := TList.Create;
  231. try
  232. //should not
  233. List.Clear;
  234. ds.GetFieldList(List, '');
  235. AssertEquals(0, List.Count);
  236. List.Clear;
  237. ExceptionRaised := False;
  238. try
  239. ds.GetFieldList(List, ' ');
  240. except
  241. on E: EDatabaseError do ExceptionRaised := True;
  242. end;
  243. AssertTrue(ExceptionRaised);
  244. List.Clear;
  245. ds.GetFieldList(List, 'Field1');
  246. AssertEquals(1, List.Count);
  247. List.Clear;
  248. ds.GetFieldList(List, ' Field1 ');
  249. AssertEquals(1, List.Count);
  250. List.Clear;
  251. ds.GetFieldList(List, 'Field1;Field2');
  252. AssertEquals(2, List.Count);
  253. List.Clear;
  254. ds.GetFieldList(List, 'Field1;Field2;');
  255. AssertEquals(2, List.Count);
  256. List.Clear;
  257. ds.GetFieldList(List, 'Field1;Field2;Field3');
  258. AssertEquals(3, List.Count);
  259. finally
  260. List.Destroy;
  261. end;
  262. finally
  263. ds.Destroy;
  264. end;
  265. end;
  266. procedure TTestBasics.TestGetParamList;
  267. var
  268. Params: TParams;
  269. P: TParam;
  270. List: TList;
  271. ExceptionRaised: Boolean;
  272. begin
  273. Params := TParams.Create(nil);
  274. try
  275. P := TParam.Create(Params, ptInput);
  276. P.Name := 'Param1';
  277. P := TParam.Create(Params, ptInput);
  278. P.Name := 'Param2';
  279. P := TParam.Create(Params, ptInput);
  280. P.Name := 'Param3';
  281. List := TList.Create;
  282. try
  283. List.Clear;
  284. Params.GetParamList(List, '');
  285. AssertEquals(0, List.Count);
  286. List.Clear;
  287. ExceptionRaised := False;
  288. try
  289. Params.GetParamList(List, ' ');
  290. except
  291. on E: EDatabaseError do ExceptionRaised := True;
  292. end;
  293. AssertTrue(ExceptionRaised);
  294. List.Clear;
  295. Params.GetParamList(List, 'Param1');
  296. AssertEquals(1, List.Count);
  297. List.Clear;
  298. Params.GetParamList(List, ' Param1 ');
  299. AssertEquals(1, List.Count);
  300. List.Clear;
  301. Params.GetParamList(List, 'Param1;');
  302. AssertEquals(1, List.Count);
  303. List.Clear;
  304. Params.GetParamList(List, 'Param1;Param2');
  305. AssertEquals(2, List.Count);
  306. List.Clear;
  307. Params.GetParamList(List, 'Param1;Param2;Param3');
  308. AssertEquals(3, List.Count);
  309. finally
  310. List.Destroy;
  311. end;
  312. finally
  313. Params.Destroy;
  314. end;
  315. end;
  316. procedure TTestBasics.TestExtractFieldName;
  317. var
  318. i: Integer;
  319. Fields: String;
  320. FieldName: String;
  321. begin
  322. Fields := '';
  323. i := 1;
  324. FieldName := ExtractFieldName(Fields, i);
  325. AssertEquals(1, i);
  326. AssertEquals('', FieldName);
  327. Fields := 'test';
  328. i := 1;
  329. FieldName := ExtractFieldName(Fields, i);
  330. AssertEquals(5, i);
  331. AssertEquals('test', FieldName);
  332. Fields := 'test;';
  333. i := 1;
  334. FieldName := ExtractFieldName(Fields, i);
  335. AssertEquals(6, i);
  336. AssertEquals('test', FieldName);
  337. Fields := ' test ';
  338. i := 1;
  339. FieldName := ExtractFieldName(Fields, i);
  340. AssertEquals(7, i);
  341. AssertEquals('test', FieldName);
  342. Fields := 'test;xxx';
  343. i := 1;
  344. FieldName := ExtractFieldName(Fields, i);
  345. AssertEquals(6, i);
  346. AssertEquals('test', FieldName);
  347. FieldName := ExtractFieldName(Fields, i);
  348. AssertEquals(9, i);
  349. AssertEquals('xxx', FieldName);
  350. end;
  351. procedure TTestBasics.TestCheckFieldNames;
  352. var
  353. ds: TDataSet;
  354. ExceptionRaised: Boolean;
  355. begin
  356. ds := CreateDatasetWith3Fields;
  357. try
  358. ExceptionRaised := False;
  359. try
  360. ds.Fields.CheckFieldNames('');
  361. except
  362. ExceptionRaised := True;
  363. end;
  364. AssertFalse(ExceptionRaised);
  365. ExceptionRaised := False;
  366. try
  367. ds.Fields.CheckFieldNames('Field1;Field2');
  368. except
  369. ExceptionRaised := True;
  370. end;
  371. AssertFalse(ExceptionRaised);
  372. ExceptionRaised := False;
  373. try
  374. ds.Fields.CheckFieldNames('Field1;NonExistentField');
  375. except
  376. ExceptionRaised := True;
  377. end;
  378. AssertTrue(ExceptionRaised);
  379. finally
  380. ds.Destroy;
  381. end;
  382. end;
  383. procedure TTestBasics.TestFindField;
  384. var
  385. ds: TDataSet;
  386. F: TField;
  387. begin
  388. ds := CreateDatasetWith3Fields;
  389. try
  390. F := ds.FindField('');
  391. AssertTrue(F = nil);
  392. F := ds.FindField('field3');
  393. AssertTrue(F <> nil);
  394. F := ds.FindField('NonExistentField');
  395. AssertTrue(F = nil);
  396. finally
  397. ds.Destroy;
  398. end;
  399. end;
  400. initialization
  401. RegisterTest(TTestBasics);
  402. end.