testsqlfieldtypes.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. unit TestSQLFieldTypes;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, testutils, testregistry,
  6. db;
  7. type
  8. TParamProc = procedure(AParam:TParam; i : integer);
  9. TFieldProc = procedure(AField:TField; i : integer);
  10. { TTestFieldTypes }
  11. TTestFieldTypes= class(TTestCase)
  12. private
  13. procedure CreateTableWithFieldType(ADatatype : TFieldType; ASQLTypeDecl : string);
  14. procedure TestFieldDeclaration(ADatatype: TFieldType; ADataSize: integer);
  15. procedure TestXXParamQuery(ADatatype : TFieldType; ASQLTypeDecl : string; testValuescount : integer; Cross : boolean = false);
  16. protected
  17. procedure SetUp; override;
  18. procedure TearDown; override;
  19. procedure RunTest; override;
  20. published
  21. procedure TestCrossStringDateParam;
  22. procedure TestGetFieldNames;
  23. procedure TestUpdateIndexDefs;
  24. procedure TestSetBlobAsMemoParam;
  25. procedure TestSetBlobAsStringParam;
  26. procedure TestGetIndexDefs;
  27. procedure TestDblQuoteEscComments;
  28. procedure TestpfInUpdateFlag; // bug 7565
  29. procedure TestInt;
  30. procedure TestScript;
  31. procedure TestTemporaryTable;
  32. procedure TestParametersAndDates;
  33. procedure TestExceptOnsecClose;
  34. procedure TestBlob;
  35. procedure TestChangeBlob;
  36. procedure TestBlobGetText;
  37. procedure TestLargeRecordSize;
  38. procedure TestNumeric;
  39. procedure TestFloat;
  40. procedure TestDateTime; // bug 6925
  41. procedure TestString;
  42. procedure TestUnlVarChar;
  43. procedure TestDate;
  44. procedure TestNullValues;
  45. procedure TestParamQuery;
  46. procedure TestStringParamQuery;
  47. procedure TestDateParamQuery;
  48. procedure TestIntParamQuery;
  49. procedure TestFloatParamQuery;
  50. procedure TestAggregates;
  51. end;
  52. implementation
  53. uses sqldbtoolsunit,toolsunit, variants, sqldb, bufdataset;
  54. Type HackedDataset = class(TDataset);
  55. const
  56. testFloatValuesCount = 21;
  57. testFloatValues : Array[0..testFloatValuesCount-1] of double = (-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,0.123456,-0.123456,4.35,12.434E7,9.876e-5,123.45678);
  58. testIntValuesCount = 17;
  59. testIntValues : Array[0..testIntValuesCount-1] of integer = (-maxInt,-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,MaxInt);
  60. testStringValuesCount = 20;
  61. testStringValues : Array[0..testStringValuesCount-1] of string = (
  62. '',
  63. 'a',
  64. 'ab',
  65. 'abc',
  66. 'abcd',
  67. 'abcde',
  68. 'abcdef',
  69. 'abcdefg',
  70. 'abcdefgh',
  71. 'abcdefghi',
  72. 'abcdefghij',
  73. 'lMnOpQrStU',
  74. '1234567890',
  75. '_!@#$%^&*(',
  76. ' ''quotes'' ',
  77. ')-;:/?.<>',
  78. '~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
  79. ' WRaP ',
  80. 'wRaP ',
  81. ' wRAP'
  82. );
  83. testDateValuesCount = 18;
  84. testDateValues : Array[0..testDateValuesCount-1] of string = (
  85. '2000-01-01',
  86. '1999-12-31',
  87. '2004-02-29',
  88. '2004-03-01',
  89. '1991-02-28',
  90. '1991-03-01',
  91. '2040-10-16',
  92. '1977-09-29',
  93. '1800-03-30',
  94. '1650-05-10',
  95. '1754-06-04',
  96. '0904-04-12',
  97. '0199-07-09',
  98. '0001-01-01',
  99. '1899-12-29',
  100. '1899-12-30',
  101. '1899-12-31',
  102. '1900-01-01'
  103. );
  104. procedure TTestFieldTypes.TestpfInUpdateFlag;
  105. var ds : TBufDataset;
  106. AFld1, AFld2, AFld3 : Tfield;
  107. begin
  108. ds := (DBConnector.GetNDataset(True,5) as TBufDataset);
  109. with ds do
  110. begin
  111. AFld1 := TIntegerField.Create(ds);
  112. AFld1.FieldName := 'ID';
  113. AFld1.DataSet := ds;
  114. AFld1.ProviderFlags := AFld1.ProviderFlags + [pfInKey];
  115. AFld2 := TStringField.Create(ds);
  116. AFld2.FieldName := 'NAME';
  117. AFld2.DataSet := ds;
  118. AFld3 := TIntegerField.Create(ds);
  119. AFld3.FieldName := 'CALCFLD';
  120. AFld3.DataSet := ds;
  121. Afld3.FieldKind := fkCalculated;
  122. AFld3.ProviderFlags := [];
  123. Open;
  124. Edit;
  125. FieldByName('ID').AsInteger := 254;
  126. Post;
  127. ApplyUpdates;
  128. Append;
  129. FieldByName('ID').AsInteger := 255;
  130. Post;
  131. ApplyUpdates;
  132. Close;
  133. AFld1.Free;
  134. AFld2.Free;
  135. AFld3.Free;
  136. end;
  137. end;
  138. procedure TTestFieldTypes.TestScript;
  139. var Ascript : TSQLScript;
  140. begin
  141. Ascript := tsqlscript.create(nil);
  142. with Ascript do
  143. begin
  144. DataBase := TSQLDBConnector(DBConnector).Connection;
  145. transaction := TSQLDBConnector(DBConnector).Transaction;
  146. script.clear;
  147. script.append('create table a (id int);');
  148. script.append('create table b (id int);');
  149. ExecuteScript;
  150. end;
  151. end;
  152. procedure TTestFieldTypes.TestInt;
  153. var
  154. i : byte;
  155. begin
  156. CreateTableWithFieldType(ftInteger,'INT');
  157. TestFieldDeclaration(ftInteger,4);
  158. for i := 0 to testIntValuesCount-1 do
  159. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + inttostr(testIntValues[i]) + ')');
  160. with TSQLDBConnector(DBConnector).Query do
  161. begin
  162. Open;
  163. for i := 0 to testIntValuesCount-1 do
  164. begin
  165. AssertEquals(testIntValues[i],fields[0].AsInteger);
  166. Next;
  167. end;
  168. close;
  169. end;
  170. end;
  171. procedure TTestFieldTypes.TestLargeRecordSize;
  172. var
  173. i : byte;
  174. begin
  175. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (plant varchar(8192),sampling_type varchar(8192),area varchar(8192), area_description varchar(8192), batch varchar(8192), sampling_datetime timestamp, status varchar(8192), batch_commentary varchar(8192))');
  176. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  177. if UpperCase(dbconnectorparams)='INTERBASE' then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  178. with TSQLDBConnector(DBConnector).Query do
  179. begin
  180. sql.clear;
  181. sql.append('insert into FPDEV2 (plant,sampling_type,batch,sampling_datetime,status,batch_commentary) values (''ZUBNE PASTE'',''OTISCI POVR￿INA'',''000037756'',''2005-07-01'',''NE ODGOVARA'',''Ovdje se upisuje komentar o kontrolnom broju..............'')');
  182. ExecSQL;
  183. sql.clear;
  184. sql.append('select * from FPDEV2');
  185. open;
  186. AssertEquals('ZUBNE PASTE',FieldByName('plant').AsString);
  187. AssertEquals(EncodeDate(2005,07,01),FieldByName('sampling_datetime').AsDateTime);
  188. close;
  189. end;
  190. end;
  191. procedure TTestFieldTypes.TestNumeric;
  192. const
  193. testValuesCount = 13;
  194. testValues : Array[0..testValuesCount-1] of currency = (-123456.789,-10200,-10000,-1875.25,-10,-0.5,0,0.5,10,1875.25,10000,10200,123456.789);
  195. var
  196. i : byte;
  197. begin
  198. CreateTableWithFieldType(ftBCD,'NUMERIC(10,4)');
  199. TestFieldDeclaration(ftBCD,sizeof(Currency));
  200. for i := 0 to testValuesCount-1 do
  201. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + CurrToStrF(testValues[i],ffFixed,3) + ')');
  202. with TSQLDBConnector(DBConnector).Query do
  203. begin
  204. Open;
  205. for i := 0 to testValuesCount-1 do
  206. begin
  207. AssertEquals(testValues[i],fields[0].AsCurrency);
  208. Next;
  209. end;
  210. close;
  211. end;
  212. end;
  213. procedure TTestFieldTypes.TestString;
  214. const
  215. testValuesCount = 19;
  216. testValues : Array[0..testValuesCount-1] of string = (
  217. '',
  218. 'a',
  219. 'ab',
  220. 'abc',
  221. 'abcd',
  222. 'abcde',
  223. 'abcdef',
  224. 'abcdefg',
  225. 'abcdefgh',
  226. 'abcdefghi',
  227. 'abcdefghij',
  228. 'lMnOpQrStU',
  229. '1234567890',
  230. '_!@#$%^&*(',
  231. ')-;:/?.<>',
  232. '~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
  233. ' WRaP ',
  234. 'wRaP ',
  235. ' wRAP'
  236. );
  237. var
  238. i : byte;
  239. begin
  240. CreateTableWithFieldType(ftString,'VARCHAR(10)');
  241. TestFieldDeclaration(ftString,11);
  242. for i := 0 to testValuesCount-1 do
  243. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  244. with TSQLDBConnector(DBConnector).Query do
  245. begin
  246. Open;
  247. for i := 0 to testValuesCount-1 do
  248. begin
  249. if (SQLDbType in MySQLdbTypes) then
  250. AssertEquals(TrimRight(testValues[i]),fields[0].AsString) // MySQL automatically trims strings
  251. else
  252. AssertEquals(testValues[i],fields[0].AsString);
  253. Next;
  254. end;
  255. close;
  256. end;
  257. end;
  258. procedure TTestFieldTypes.TestUnlVarChar;
  259. const
  260. testValuesCount = 21;
  261. testValues : Array[0..testValuesCount-1] of string = (
  262. '',
  263. 'a',
  264. 'ab',
  265. 'abc',
  266. 'abcd',
  267. 'abcde',
  268. 'abcdef',
  269. 'abcdefg',
  270. 'abcdefgh',
  271. 'abcdefghi',
  272. 'abcdefghij',
  273. 'lMnOpQrStU',
  274. '1234567890',
  275. '_!@#$%^&*(',
  276. ')-;:/?.<>',
  277. '~`|{}- =',
  278. ' WRaP ',
  279. 'wRaP ',
  280. ' wRAP',
  281. '0123456789',
  282. 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?' + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?'
  283. + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?' + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?'
  284. );
  285. var
  286. i : byte;
  287. begin
  288. // AssertTrue(SIgnoreAssertion,SQLDbType = postgresql); // Only postgres accept this type-definition
  289. CreateTableWithFieldType(ftString,'VARCHAR');
  290. TestFieldDeclaration(ftString,dsMaxStringSize+1);
  291. for i := 0 to testValuesCount-1 do
  292. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  293. with TSQLDBConnector(DBConnector).Query do
  294. begin
  295. Open;
  296. for i := 0 to testValuesCount-1 do
  297. begin
  298. AssertEquals(testValues[i],fields[0].AsString);
  299. Next;
  300. end;
  301. close;
  302. end;
  303. end;
  304. procedure TTestFieldTypes.TestDate;
  305. var
  306. i : byte;
  307. begin
  308. CreateTableWithFieldType(ftDate,'DATE');
  309. TestFieldDeclaration(ftDate,8);
  310. for i := 0 to testDateValuesCount-1 do
  311. if SQLDbType=oracle then
  312. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testDateValues[i] + ''',''YYYY-MM-DD''))')
  313. else
  314. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testDateValues[i] + ''')');
  315. // TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  316. with TSQLDBConnector(DBConnector).Query do
  317. begin
  318. Open;
  319. for i := 0 to testDateValuesCount-1 do
  320. begin
  321. AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime));
  322. Next;
  323. end;
  324. close;
  325. end;
  326. end;
  327. procedure TTestFieldTypes.TestChangeBlob;
  328. var s : string;
  329. begin
  330. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT blob)');
  331. // TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT text)');
  332. TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For interbase
  333. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (ID,FT) values (1,''Test deze blob'')');
  334. with TSQLDBConnector(DBConnector).Query do
  335. begin
  336. sql.clear;
  337. sql.add('select * from FPDEV2');
  338. Open;
  339. fields[1].ProviderFlags := [pfInUpdate]; // blob niet in de where
  340. UpdateMode := upWhereAll;
  341. AssertEquals('Test deze blob',fields[1].AsString);
  342. edit;
  343. // Dat werkt niet lekker, omdat de stream vernield wordt...
  344. // fields[0].asstring := 'Deze blob is gewijzigd!';
  345. With Createblobstream(fields[1],bmwrite) do
  346. begin
  347. s := 'Deze blob is gewijzigd!';
  348. WriteBuffer(Pointer(s)^,Length(s));
  349. post;
  350. free;
  351. end;
  352. AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
  353. ApplyUpdates(0);
  354. TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  355. close;
  356. open;
  357. AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
  358. close;
  359. end;
  360. end;
  361. procedure TTestFieldTypes.TestBlobGetText;
  362. begin
  363. CreateTableWithFieldType(ftBlob,'BLOB');
  364. // CreateTableWithFieldType(ftBlob,'TEXT');
  365. TestFieldDeclaration(ftBlob,0);
  366. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''Test deze blob'')');
  367. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (Null)');
  368. // TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  369. with TSQLDBConnector(DBConnector).Query do
  370. begin
  371. Open;
  372. AssertFalse(fields[0].IsNull);
  373. AssertEquals('(BLOB)',fields[0].DisplayText);
  374. AssertEquals('Test deze blob',fields[0].AsString);
  375. Next;
  376. AssertTrue(fields[0].IsNull);
  377. AssertEquals('(blob)',fields[0].Text);
  378. AssertEquals('',fields[0].AsString);
  379. close;
  380. end;
  381. end;
  382. procedure TTestFieldTypes.TestSetBlobAsStringParam;
  383. var
  384. i : byte;
  385. ASQL : TSQLQuery;
  386. begin
  387. CreateTableWithFieldType(ftBlob,'BLOB');
  388. // CreateTableWithFieldType(ftBlob,'TEXT');
  389. TestFieldDeclaration(ftBlob,0);
  390. ASQL := DBConnector.GetNDataset(True,1) as tsqlquery;
  391. with ASql do
  392. begin
  393. sql.Text := 'insert into FPDEV2 (FT) values (:BlobParam)';
  394. Params.ParamByName('blobParam').AsString := 'Test deze BLob';
  395. ExecSQL;
  396. end;
  397. with TSQLDBConnector(DBConnector).Query do
  398. begin
  399. Open;
  400. if not eof then
  401. AssertEquals('Test deze BLob',fields[0].AsString);
  402. close;
  403. end;
  404. end;
  405. procedure TTestFieldTypes.TestBlob;
  406. var
  407. i : byte;
  408. begin
  409. CreateTableWithFieldType(ftBlob,'BLOB');
  410. // CreateTableWithFieldType(ftBlob,'TEXT');
  411. TestFieldDeclaration(ftBlob,0);
  412. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''Test deze blob'')');
  413. // TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  414. with TSQLDBConnector(DBConnector).Query do
  415. begin
  416. Open;
  417. AssertEquals('Test deze blob',fields[0].AsString);
  418. close;
  419. end;
  420. end;
  421. procedure TTestFieldTypes.TestDateTime;
  422. const
  423. testValuesCount = 31;
  424. testValues : Array[0..testValuesCount-1] of string = (
  425. '2000-01-01',
  426. '1999-12-31',
  427. '2004-02-29',
  428. '2004-03-01',
  429. '1991-02-28',
  430. '1991-03-01',
  431. '1977-09-29',
  432. '2000-01-01 10:00:00',
  433. '2000-01-01 23:59:59',
  434. '1994-03-06 11:54:30',
  435. '2040-10-16', // MySQL 4.0 doesn't support datetimes before 1970 or after 2038
  436. '1400-02-03 12:21:53',
  437. '0354-11-20 21:25:15',
  438. '1333-02-03 21:44:21',
  439. '1800-03-30',
  440. '1650-05-10',
  441. '1754-06-04',
  442. '0904-04-12',
  443. '0199-07-09',
  444. '0001-01-01',
  445. '1899-12-29',
  446. '1899-12-30',
  447. '1899-12-31',
  448. '1900-01-01',
  449. '1899-12-30 18:00:51',
  450. '1899-12-30 04:00:51',
  451. '1899-12-29 04:00:51',
  452. '1899-12-29 18:00:51',
  453. '1903-04-02 01:04:02',
  454. '1815-09-24 03:47:22',
  455. '2100-01-01 01:01:01'
  456. );
  457. var
  458. i, corrTestValueCount : byte;
  459. begin
  460. CreateTableWithFieldType(ftDateTime,'TIMESTAMP');
  461. TestFieldDeclaration(ftDateTime,8);
  462. if SQLDbType=mysql40 then corrTestValueCount := testValuesCount-21
  463. else corrTestValueCount := testValuesCount;
  464. for i := 0 to corrTestValueCount-1 do
  465. if SQLDbType=oracle then
  466. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testValues[i] + ''',''YYYY-MM-DD HH24:MI:SS''))')
  467. else
  468. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  469. with TSQLDBConnector(DBConnector).Query do
  470. begin
  471. Open;
  472. for i := 0 to corrTestValueCount-1 do
  473. begin
  474. if length(testValues[i]) < 12 then
  475. AssertEquals(testValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime))
  476. else
  477. AssertEquals(testValues[i],FormatDateTime('yyyy/mm/dd hh:mm:ss',fields[0].AsDateTime));
  478. Next;
  479. end;
  480. close;
  481. end;
  482. end;
  483. procedure TTestFieldTypes.TestFloat;
  484. const
  485. testValuesCount = 21;
  486. testValues : Array[0..testValuesCount-1] of double = (-maxSmallint-1,-maxSmallint,-256,-255,-128,-127,-1,0,1,127,128,255,256,maxSmallint,maxSmallint+1,0.123456,-0.123456,4.35,12.434E7,9.876e-5,123.45678);
  487. var
  488. i : byte;
  489. begin
  490. CreateTableWithFieldType(ftFloat,'FLOAT');
  491. TestFieldDeclaration(ftFloat,sizeof(double));
  492. for i := 0 to testValuesCount-1 do
  493. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + floattostr(testValues[i]) + ')');
  494. with TSQLDBConnector(DBConnector).Query do
  495. begin
  496. Open;
  497. for i := 0 to testValuesCount-1 do
  498. begin
  499. AssertEquals(testValues[i],fields[0].AsFloat);
  500. Next;
  501. end;
  502. close;
  503. end;
  504. end;
  505. procedure TTestFieldTypes.TestNullValues;
  506. begin
  507. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT)');
  508. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  509. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  510. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FIELD1) values (1)');
  511. with TSQLDBConnector(DBConnector).Query do
  512. begin
  513. sql.clear;
  514. sql.append('select * from FPDEV2');
  515. open;
  516. AssertEquals(1,FieldByName('FIELD1').AsInteger);
  517. AssertTrue('Null-values test failed',FieldByName('FIELD2').IsNull);
  518. close;
  519. end;
  520. end;
  521. procedure TTestFieldTypes.TestParamQuery;
  522. begin
  523. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT, FIELD3 INT, DECOY VARCHAR(30))');
  524. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  525. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  526. with TSQLDBConnector(DBConnector).Query do
  527. begin
  528. sql.clear;
  529. sql.append('insert into FPDEV2 (field1) values (:field1)');
  530. Params.ParamByName('field1').AsInteger := 1;
  531. ExecSQL;
  532. sql.clear;
  533. sql.append('insert into FPDEV2 (field1,field2,decoy) values (:field1,:field2,''decoytest'')');
  534. Params.ParamByName('field1').AsInteger := 2;
  535. Params.ParamByName('field2').DataType := ftInteger;
  536. Params.ParamByName('field2').Value := Null;
  537. ExecSQL;
  538. sql.clear;
  539. sql.append('insert into FPDEV2 (field1,field2,field3) values (:field1,:field2,:field3)');
  540. Params.ParamByName('field1').AsInteger := 3;
  541. Params.ParamByName('field2').AsInteger := 2;
  542. Params.ParamByName('field3').AsInteger := 3;
  543. ExecSQL;
  544. sql.clear;
  545. sql.append('insert into FPDEV2 (field1,field2,field3,decoy) values (:field1,:field2,:field3,'':decoy ::test $decoy2 $$2'')');
  546. Params.ParamByName('field1').AsInteger := 4;
  547. Params.ParamByName('field2').AsInteger := 2;
  548. Params.ParamByName('field3').AsInteger := 3;
  549. ExecSQL;
  550. sql.clear;
  551. sql.append('insert into FPDEV2 (field1,field2,field3) values (:field1,:field2,:field1)');
  552. Params.ParamByName('field1').AsInteger := 5;
  553. Params.ParamByName('field2').AsInteger := 2;
  554. ExecSQL;
  555. sql.clear;
  556. sql.append('select * from FPDEV2 order by FIELD1');
  557. open;
  558. AssertEquals(1,FieldByName('FIELD1').asinteger);
  559. AssertTrue(FieldByName('FIELD2').IsNull);
  560. AssertTrue(FieldByName('FIELD3').IsNull);
  561. AssertTrue(FieldByName('DECOY').IsNull);
  562. next;
  563. AssertEquals(2,FieldByName('FIELD1').asinteger);
  564. AssertTrue(FieldByName('FIELD2').IsNull);
  565. AssertTrue(FieldByName('FIELD3').IsNull);
  566. AssertEquals('decoytest',FieldByName('DECOY').AsString);
  567. next;
  568. AssertEquals(3,FieldByName('FIELD1').asinteger);
  569. AssertEquals(2,FieldByName('FIELD2').asinteger);
  570. AssertEquals(3,FieldByName('FIELD3').asinteger);
  571. AssertTrue(FieldByName('DECOY').IsNull);
  572. next;
  573. AssertEquals(4,FieldByName('FIELD1').asinteger);
  574. AssertEquals(2,FieldByName('FIELD2').asinteger);
  575. AssertEquals(3,FieldByName('FIELD3').asinteger);
  576. AssertEquals(':decoy ::test $decoy2 $$2',FieldByName('DECOY').AsString);
  577. next;
  578. AssertEquals(5,FieldByName('FIELD1').asinteger);
  579. AssertEquals(2,FieldByName('FIELD2').asinteger);
  580. AssertEquals(5,FieldByName('FIELD3').asinteger);
  581. AssertTrue(FieldByName('DECOY').IsNull);
  582. close;
  583. end;
  584. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  585. end;
  586. procedure TTestFieldTypes.TestIntParamQuery;
  587. begin
  588. TestXXParamQuery(ftInteger,'INT',testIntValuesCount);
  589. end;
  590. procedure TTestFieldTypes.TestFloatParamQuery;
  591. begin
  592. TestXXParamQuery(ftFloat,'FLOAT',testFloatValuesCount);
  593. end;
  594. procedure TTestFieldTypes.TestStringParamQuery;
  595. begin
  596. TestXXParamQuery(ftString,'VARCHAR(10)',testStringValuesCount);
  597. end;
  598. procedure TTestFieldTypes.TestDateParamQuery;
  599. begin
  600. TestXXParamQuery(ftDate,'DATE',testDateValuesCount);
  601. end;
  602. procedure TTestFieldTypes.TestXXParamQuery(ADatatype : TFieldType; ASQLTypeDecl : string; testValuescount : integer; Cross : boolean = false);
  603. var i : integer;
  604. begin
  605. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID INT, FIELD1 '+ASQLTypeDecl+')');
  606. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  607. if SQLDbType=interbase then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  608. with TSQLDBConnector(DBConnector).Query do
  609. begin
  610. sql.clear;
  611. sql.append('insert into FPDEV2 (ID,FIELD1) values (:id,:field1)');
  612. ShortDateFormat := 'yyyy-mm-dd';
  613. for i := 0 to testValuesCount -1 do
  614. begin
  615. Params.ParamByName('id').AsInteger := i;
  616. case ADataType of
  617. ftInteger: Params.ParamByName('field1').asinteger := testIntValues[i];
  618. ftFloat : Params.ParamByName('field1').AsFloat := testFloatValues[i];
  619. ftString : Params.ParamByName('field1').AsString := testStringValues[i];
  620. ftDate : if cross then
  621. Params.ParamByName('field1').AsString:= testDateValues[i]
  622. else
  623. Params.ParamByName('field1').AsDateTime:= StrToDate(testDateValues[i]);
  624. else
  625. AssertTrue('no test for paramtype available',False);
  626. end;
  627. ExecSQL;
  628. end;
  629. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  630. sql.clear;
  631. sql.append('select * from FPDEV2 order by ID');
  632. open;
  633. for i := 0 to testValuesCount -1 do
  634. begin
  635. AssertEquals(i,FieldByName('ID').AsInteger);
  636. case ADataType of
  637. ftInteger: AssertEquals(testIntValues[i],FieldByName('FIELD1').AsInteger);
  638. ftFloat : AssertEquals(testFloatValues[i],FieldByName('FIELD1').AsFloat);
  639. ftString : AssertEquals(testStringValues[i],FieldByName('FIELD1').AsString);
  640. ftdate : AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',FieldByName('FIELD1').AsDateTime));
  641. else
  642. AssertTrue('no test for paramtype available',False);
  643. end;
  644. Next;
  645. end;
  646. close;
  647. end;
  648. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  649. end;
  650. procedure TTestFieldTypes.TestAggregates;
  651. begin
  652. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT)');
  653. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  654. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  655. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (1,1)');
  656. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (2,3)');
  657. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (3,4)');
  658. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (4,4)');
  659. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  660. with TSQLDBConnector(DBConnector).Query do
  661. begin
  662. sql.clear;
  663. sql.append('select count(*) from FPDEV2');
  664. open;
  665. AssertEquals(4,Fields[0].AsInteger);
  666. close;
  667. sql.clear;
  668. sql.append('select sum(FIELD1) from FPDEV2');
  669. open;
  670. AssertEquals(10,Fields[0].AsInteger);
  671. close;
  672. sql.clear;
  673. sql.append('select avg(FIELD2) from FPDEV2');
  674. open;
  675. AssertEquals(3,Fields[0].AsInteger);
  676. close;
  677. end;
  678. end;
  679. procedure TTestFieldTypes.CreateTableWithFieldType(ADatatype: TFieldType;
  680. ASQLTypeDecl: string);
  681. begin
  682. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FT ' +ASQLTypeDecl+ ')');
  683. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  684. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  685. end;
  686. procedure TTestFieldTypes.TestFieldDeclaration(ADatatype: TFieldType;
  687. ADataSize: integer);
  688. begin
  689. with TSQLDBConnector(DBConnector).Query do
  690. begin
  691. SQL.Clear;
  692. SQL.Add('select * from FPDEV2');
  693. Open;
  694. AssertEquals(1,FieldCount);
  695. AssertTrue(CompareText('FT',fields[0].FieldName)=0);
  696. AssertEquals(ADataSize,fields[0].DataSize);
  697. AssertTrue(ADatatype=fields[0].DataType);
  698. Close;
  699. end;
  700. end;
  701. procedure TTestFieldTypes.SetUp;
  702. begin
  703. InitialiseDBConnector;
  704. end;
  705. procedure TTestFieldTypes.TearDown;
  706. begin
  707. if assigned(DBConnector) then
  708. TSQLDBConnector(DBConnector).Transaction.Rollback;
  709. FreeAndNil(DBConnector);
  710. end;
  711. procedure TTestFieldTypes.RunTest;
  712. begin
  713. // if (SQLDbType in TSQLDBTypes) then
  714. inherited RunTest;
  715. end;
  716. procedure TTestFieldTypes.TestCrossStringDateParam;
  717. begin
  718. TestXXParamQuery(ftDate,'DATE',testDateValuesCount,True);
  719. end;
  720. procedure TTestFieldTypes.TestGetFieldNames;
  721. var FieldNames : TStringList;
  722. begin
  723. with TSQLDBConnector(DBConnector) do
  724. begin
  725. FieldNames := TStringList.Create;
  726. try
  727. Connection.GetFieldNames('FpDEv',FieldNames);
  728. AssertEquals(2,FieldNames.Count);
  729. AssertEquals('ID',UpperCase(FieldNames[0]));
  730. AssertEquals('NAME',UpperCase(FieldNames[1]));
  731. finally
  732. FieldNames.Free;
  733. end;
  734. end;
  735. end;
  736. procedure TTestFieldTypes.TestUpdateIndexDefs;
  737. var ds : TSQLQuery;
  738. begin
  739. ds := DBConnector.GetNDataset(1) as TSQLQuery;
  740. ds.Prepare;
  741. ds.IndexDefs.Update;
  742. AssertEquals(1,ds.IndexDefs.count);
  743. AssertEquals('ID',ds.indexdefs[0].Fields);
  744. Asserttrue(ds.indexdefs[0].Options=[ixPrimary,ixUnique]);
  745. ds.IndexDefs.Update;
  746. AssertEquals(1,ds.IndexDefs.count);
  747. AssertEquals('ID',ds.indexdefs[0].Fields);
  748. Asserttrue(ds.indexdefs[0].Options=[ixPrimary,ixUnique]);
  749. end;
  750. procedure TTestFieldTypes.TestSetBlobAsMemoParam;
  751. var
  752. i : byte;
  753. ASQL : TSQLQuery;
  754. begin
  755. CreateTableWithFieldType(ftBlob,'BLOB');
  756. // CreateTableWithFieldType(ftBlob,'TEXT');
  757. TestFieldDeclaration(ftBlob,0);
  758. ASQL := DBConnector.GetNDataset(True,1) as tsqlquery;
  759. with ASql do
  760. begin
  761. sql.Text := 'insert into FPDEV2 (FT) values (:BlobParam)';
  762. Params.ParamByName('blobParam').AsMemo := 'Test deze BLob';
  763. ExecSQL;
  764. end;
  765. with TSQLDBConnector(DBConnector).Query do
  766. begin
  767. Open;
  768. if not eof then
  769. AssertEquals('Test deze BLob',fields[0].AsString);
  770. close;
  771. end;
  772. end;
  773. procedure TTestFieldTypes.TestTemporaryTable;
  774. begin
  775. with TSQLDBConnector(DBConnector).Query do
  776. begin
  777. SQL.Clear;
  778. SQL.Add('CREATE TEMPORARY TABLE TEMP1 (id int)');
  779. ExecSQL;
  780. SQL.Text := 'INSERT INTO TEMP1(id) values (5)';
  781. ExecSQL;
  782. SQL.Text := 'SELECT * FROM TEMP1';
  783. Open;
  784. AssertEquals(5,fields[0].AsInteger);
  785. Close;
  786. end;
  787. end;
  788. procedure TTestFieldTypes.TestGetIndexDefs;
  789. var ds : TSQLQuery;
  790. inddefs : TIndexDefs;
  791. begin
  792. ds := DBConnector.GetNDataset(1) as TSQLQuery;
  793. ds.Open;
  794. AssertEquals(1,ds.IndexDefs.count);
  795. inddefs := HackedDataset(ds).GetIndexDefs(ds.IndexDefs,[ixPrimary]);
  796. AssertEquals(1,inddefs.count);
  797. AssertEquals('ID',inddefs[0].Fields);
  798. Asserttrue(inddefs[0].Options=[ixPrimary,ixUnique]);
  799. inddefs.Free;
  800. inddefs := HackedDataset(ds).GetIndexDefs(ds.IndexDefs,[ixPrimary,ixUnique]);
  801. AssertEquals(1,inddefs.count);
  802. AssertEquals('ID',inddefs[0].Fields);
  803. Asserttrue(inddefs[0].Options=[ixPrimary,ixUnique]);
  804. inddefs.Free;
  805. inddefs := HackedDataset(ds).GetIndexDefs(ds.IndexDefs,[ixDescending]);
  806. AssertEquals(0,inddefs.count);
  807. inddefs.Free;
  808. end;
  809. procedure TTestFieldTypes.TestDblQuoteEscComments;
  810. begin
  811. with TSQLDBConnector(DBConnector).Query do
  812. begin
  813. SQL.Clear;
  814. SQL.Add('select * from FPDEV where name=''test '''' and :ThisIsNotAParameter ''');
  815. open;
  816. close;
  817. end;
  818. end;
  819. procedure TTestFieldTypes.TestParametersAndDates;
  820. begin
  821. with TSQLDBConnector(DBConnector).Query do
  822. begin
  823. SQL.Clear;
  824. sql.add('select now()::date as current_date where 1=1');
  825. open;
  826. first;
  827. writeln(fields[0].asstring); // return the correct date
  828. close;
  829. sql.clear;
  830. sql.add('select now()::date as current_date where cast(1 as integer) = :PARAM1');
  831. params.parambyname('PARAM1').asinteger:= 1;
  832. open;
  833. first;
  834. writeln(fields[0].asstring); // return invalid date
  835. close;
  836. end
  837. end;
  838. procedure TTestFieldTypes.TestExceptOnsecClose;
  839. begin
  840. with TSQLDBConnector(DBConnector).Query do
  841. begin
  842. SQL.Clear;
  843. SQL.Add('select * from FPDEV');
  844. Open;
  845. close;
  846. SQL.Clear;
  847. SQL.Add('select blaise from FPDEV');
  848. {$IFDEF FPC}
  849. // AssertException(EIBDatabaseError,@Open);
  850. {$ELSE}
  851. // AssertException(EIBDatabaseError,Open);
  852. {$ENDIF}
  853. Open;
  854. Close;
  855. end;
  856. end;
  857. initialization
  858. if uppercase(dbconnectorname)='SQL' then RegisterTest(TTestFieldTypes);
  859. end.