testsqlfieldtypes.pas 28 KB

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