testsqlfieldtypes.pas 30 KB

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