testfieldtypes.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448
  1. unit TestFieldTypes;
  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. procedure TestSetBlobAsParam(asWhat : integer);
  17. protected
  18. procedure SetUp; override;
  19. procedure TearDown; override;
  20. procedure RunTest; override;
  21. published
  22. procedure TestClearUpdateableStatus;
  23. procedure TestFixedStringParamQuery;
  24. procedure TestReadOnlyParseSQL; // bug 9254
  25. procedure TestParseJoins; // bug 10148
  26. procedure TestDoubleFieldNames; // bug 8457
  27. procedure TestParseUnion; // bug 8442
  28. procedure TestInsertLargeStrFields; // bug 9600
  29. procedure TestNumericNames; // Bug9661
  30. procedure Test11Params;
  31. procedure TestRowsAffected; // bug 9758
  32. procedure TestStringsReplace;
  33. procedure TestCircularParams;
  34. procedure TestBug9744;
  35. procedure TestCrossStringDateParam;
  36. procedure TestGetFieldNames;
  37. procedure TestGetTables;
  38. procedure TestUpdateIndexDefs;
  39. procedure TestSetBlobAsMemoParam;
  40. procedure TestSetBlobAsBlobParam;
  41. procedure TestSetBlobAsStringParam;
  42. procedure TestGetIndexDefs;
  43. procedure TestDblQuoteEscComments;
  44. procedure TestpfInUpdateFlag; // bug 7565
  45. procedure TestInt;
  46. procedure TestScript;
  47. procedure TestTemporaryTable;
  48. procedure TestParametersAndDates;
  49. procedure TestExceptOnsecClose;
  50. procedure TestBlob;
  51. procedure TestChangeBlob;
  52. procedure TestBlobGetText;
  53. procedure TestLargeRecordSize;
  54. procedure TestNumeric;
  55. procedure TestFloat;
  56. procedure TestDateTime; // bug 6925
  57. procedure TestString;
  58. procedure TestUnlVarChar;
  59. procedure TestDate;
  60. procedure TestNullValues;
  61. procedure TestParamQuery;
  62. procedure TestStringParamQuery;
  63. procedure TestDateParamQuery;
  64. procedure TestIntParamQuery;
  65. procedure TestFloatParamQuery;
  66. procedure TestAggregates;
  67. end;
  68. implementation
  69. uses sqldbtoolsunit,toolsunit, variants, sqldb, bufdataset, strutils;
  70. Type HackedDataset = class(TDataset);
  71. const
  72. testFloatValuesCount = 21;
  73. 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);
  74. testIntValuesCount = 17;
  75. 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);
  76. testDateValuesCount = 18;
  77. testDateValues : Array[0..testDateValuesCount-1] of string = (
  78. '2000-01-01',
  79. '1999-12-31',
  80. '2004-02-29',
  81. '2004-03-01',
  82. '1991-02-28',
  83. '1991-03-01',
  84. '2040-10-16',
  85. '1977-09-29',
  86. '1800-03-30',
  87. '1650-05-10',
  88. '1754-06-04',
  89. '0904-04-12',
  90. '0199-07-09',
  91. '0001-01-01',
  92. '1899-12-29',
  93. '1899-12-30',
  94. '1899-12-31',
  95. '1900-01-01'
  96. );
  97. procedure TTestFieldTypes.TestpfInUpdateFlag;
  98. var ds : TBufDataset;
  99. AFld1, AFld2, AFld3 : Tfield;
  100. begin
  101. ds := (DBConnector.GetNDataset(True,5) as TBufDataset);
  102. with ds do
  103. begin
  104. AFld1 := TIntegerField.Create(ds);
  105. AFld1.FieldName := 'ID';
  106. AFld1.DataSet := ds;
  107. AFld1.ProviderFlags := AFld1.ProviderFlags + [pfInKey];
  108. AFld2 := TStringField.Create(ds);
  109. AFld2.FieldName := 'NAME';
  110. AFld2.DataSet := ds;
  111. AFld3 := TIntegerField.Create(ds);
  112. AFld3.FieldName := 'CALCFLD';
  113. AFld3.DataSet := ds;
  114. Afld3.FieldKind := fkCalculated;
  115. AFld3.ProviderFlags := [];
  116. Open;
  117. Edit;
  118. FieldByName('ID').AsInteger := 254;
  119. Post;
  120. ApplyUpdates;
  121. Append;
  122. FieldByName('ID').AsInteger := 255;
  123. Post;
  124. ApplyUpdates;
  125. Close;
  126. AFld1.Free;
  127. AFld2.Free;
  128. AFld3.Free;
  129. end;
  130. end;
  131. procedure TTestFieldTypes.TestScript;
  132. var Ascript : TSQLScript;
  133. begin
  134. Ascript := tsqlscript.create(nil);
  135. try
  136. with Ascript do
  137. begin
  138. DataBase := TSQLDBConnector(DBConnector).Connection;
  139. transaction := TSQLDBConnector(DBConnector).Transaction;
  140. script.clear;
  141. script.append('create table a (id int);');
  142. script.append('create table b (id int);');
  143. ExecuteScript;
  144. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  145. if SQLDbType=interbase then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  146. end;
  147. finally
  148. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('drop table a');
  149. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('drop table b');
  150. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  151. if SQLDbType=interbase then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  152. end;
  153. end;
  154. procedure TTestFieldTypes.TestInt;
  155. var
  156. i : byte;
  157. begin
  158. CreateTableWithFieldType(ftInteger,'INT');
  159. TestFieldDeclaration(ftInteger,4);
  160. for i := 0 to testIntValuesCount-1 do
  161. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + inttostr(testIntValues[i]) + ')');
  162. with TSQLDBConnector(DBConnector).Query do
  163. begin
  164. Open;
  165. for i := 0 to testIntValuesCount-1 do
  166. begin
  167. AssertEquals(testIntValues[i],fields[0].AsInteger);
  168. Next;
  169. end;
  170. close;
  171. end;
  172. end;
  173. procedure TTestFieldTypes.TestLargeRecordSize;
  174. var
  175. i : byte;
  176. begin
  177. 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))');
  178. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  179. if UpperCase(dbconnectorparams)='INTERBASE' then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  180. with TSQLDBConnector(DBConnector).Query do
  181. begin
  182. sql.clear;
  183. 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..............'')');
  184. ExecSQL;
  185. sql.clear;
  186. sql.append('select * from FPDEV2');
  187. open;
  188. AssertEquals('ZUBNE PASTE',FieldByName('plant').AsString);
  189. AssertEquals(EncodeDate(2005,07,01),FieldByName('sampling_datetime').AsDateTime);
  190. close;
  191. end;
  192. end;
  193. procedure TTestFieldTypes.TestNumeric;
  194. const
  195. testValuesCount = 13;
  196. 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);
  197. var
  198. i : byte;
  199. begin
  200. CreateTableWithFieldType(ftBCD,'NUMERIC(10,4)');
  201. TestFieldDeclaration(ftBCD,sizeof(Currency));
  202. for i := 0 to testValuesCount-1 do
  203. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + CurrToStrF(testValues[i],ffFixed,3) + ')');
  204. with TSQLDBConnector(DBConnector).Query do
  205. begin
  206. Open;
  207. for i := 0 to testValuesCount-1 do
  208. begin
  209. AssertEquals(testValues[i],fields[0].AsCurrency);
  210. Next;
  211. end;
  212. close;
  213. end;
  214. end;
  215. procedure TTestFieldTypes.TestString;
  216. const
  217. testValuesCount = 19;
  218. testValues : Array[0..testValuesCount-1] of string = (
  219. '',
  220. 'a',
  221. 'ab',
  222. 'abc',
  223. 'abcd',
  224. 'abcde',
  225. 'abcdef',
  226. 'abcdefg',
  227. 'abcdefgh',
  228. 'abcdefghi',
  229. 'abcdefghij',
  230. 'lMnOpQrStU',
  231. '1234567890',
  232. '_!@#$%^&*(',
  233. ')-;:/?.<>',
  234. '~`|{}- =', // note that there's no \ (backslash) since some db's uses that as escape-character
  235. ' WRaP ',
  236. 'wRaP ',
  237. ' wRAP'
  238. );
  239. var
  240. i : byte;
  241. begin
  242. CreateTableWithFieldType(ftString,'VARCHAR(10)');
  243. TestFieldDeclaration(ftString,11);
  244. for i := 0 to testValuesCount-1 do
  245. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  246. with TSQLDBConnector(DBConnector).Query do
  247. begin
  248. Open;
  249. for i := 0 to testValuesCount-1 do
  250. begin
  251. if (SQLDbType in [mysql40,mysql41]) then
  252. AssertEquals(TrimRight(testValues[i]),fields[0].AsString) // MySQL < 5.0.3 automatically trims strings
  253. else
  254. AssertEquals(testValues[i],fields[0].AsString);
  255. Next;
  256. end;
  257. close;
  258. end;
  259. end;
  260. procedure TTestFieldTypes.TestUnlVarChar;
  261. const
  262. testValuesCount = 21;
  263. testValues : Array[0..testValuesCount-1] of string = (
  264. '',
  265. 'a',
  266. 'ab',
  267. 'abc',
  268. 'abcd',
  269. 'abcde',
  270. 'abcdef',
  271. 'abcdefg',
  272. 'abcdefgh',
  273. 'abcdefghi',
  274. 'abcdefghij',
  275. 'lMnOpQrStU',
  276. '1234567890',
  277. '_!@#$%^&*(',
  278. ')-;:/?.<>',
  279. '~`|{}- =',
  280. ' WRaP ',
  281. 'wRaP ',
  282. ' wRAP',
  283. '0123456789',
  284. 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?' + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?'
  285. + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?' + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !@#$%^&*()_+-=][|}{;:,./<>?'
  286. );
  287. var
  288. i : byte;
  289. begin
  290. if SQLDbType<>postgresql then Ignore('This test does only apply to Postgres, since others don''t support varchars without length given');
  291. CreateTableWithFieldType(ftString,'VARCHAR');
  292. TestFieldDeclaration(ftString,dsMaxStringSize+1);
  293. for i := 0 to testValuesCount-1 do
  294. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  295. with TSQLDBConnector(DBConnector).Query do
  296. begin
  297. Open;
  298. for i := 0 to testValuesCount-1 do
  299. begin
  300. AssertEquals(testValues[i],fields[0].AsString);
  301. Next;
  302. end;
  303. close;
  304. end;
  305. end;
  306. procedure TTestFieldTypes.TestDate;
  307. var
  308. i : byte;
  309. begin
  310. CreateTableWithFieldType(ftDate,'DATE');
  311. TestFieldDeclaration(ftDate,8);
  312. for i := 0 to testDateValuesCount-1 do
  313. if SQLDbType=oracle then
  314. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testDateValues[i] + ''',''YYYY-MM-DD''))')
  315. else
  316. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testDateValues[i] + ''')');
  317. // TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  318. with TSQLDBConnector(DBConnector).Query do
  319. begin
  320. Open;
  321. for i := 0 to testDateValuesCount-1 do
  322. begin
  323. AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime));
  324. Next;
  325. end;
  326. close;
  327. end;
  328. end;
  329. procedure TTestFieldTypes.TestChangeBlob;
  330. var s : string;
  331. begin
  332. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT '+FieldtypeDefinitions[ftblob]+')');
  333. TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For interbase
  334. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (ID,FT) values (1,''Test deze blob'')');
  335. with TSQLDBConnector(DBConnector).Query do
  336. begin
  337. sql.clear;
  338. sql.add('select * from FPDEV2');
  339. Open;
  340. fields[1].ProviderFlags := [pfInUpdate]; // blob niet in de where
  341. UpdateMode := upWhereAll;
  342. AssertEquals('Test deze blob',fields[1].AsString);
  343. edit;
  344. // Dat werkt niet lekker, omdat de stream vernield wordt...
  345. // fields[0].asstring := 'Deze blob is gewijzigd!';
  346. With Createblobstream(fields[1],bmwrite) do
  347. begin
  348. s := 'Deze blob is gewijzigd!';
  349. WriteBuffer(Pointer(s)^,Length(s));
  350. post;
  351. free;
  352. end;
  353. AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
  354. ApplyUpdates(0);
  355. TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  356. close;
  357. open;
  358. AssertEquals('Deze blob is gewijzigd!',fields[1].AsString);
  359. close;
  360. end;
  361. end;
  362. procedure TTestFieldTypes.TestBlobGetText;
  363. begin
  364. CreateTableWithFieldType(ftBlob,FieldtypeDefinitions[ftBlob]);
  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. begin
  384. TestSetBlobAsParam(1);
  385. end;
  386. procedure TTestFieldTypes.TestBlob;
  387. var
  388. i : byte;
  389. begin
  390. CreateTableWithFieldType(ftBlob,FieldtypeDefinitions[ftBlob]);
  391. TestFieldDeclaration(ftBlob,0);
  392. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''Test deze blob'')');
  393. // TSQLDBConnector(DBConnector).Transaction.CommitRetaining; // For debug-purposes
  394. with TSQLDBConnector(DBConnector).Query do
  395. begin
  396. Open;
  397. AssertEquals('Test deze blob',fields[0].AsString);
  398. close;
  399. end;
  400. end;
  401. procedure TTestFieldTypes.TestDateTime;
  402. const
  403. testValuesCount = 31;
  404. testValues : Array[0..testValuesCount-1] of string = (
  405. '2000-01-01',
  406. '1999-12-31',
  407. '2004-02-29',
  408. '2004-03-01',
  409. '1991-02-28',
  410. '1991-03-01',
  411. '1977-09-29',
  412. '2000-01-01 10:00:00',
  413. '2000-01-01 23:59:59',
  414. '1994-03-06 11:54:30',
  415. '2040-10-16', // MySQL 4.0 doesn't support datetimes before 1970 or after 2038
  416. '1400-02-03 12:21:53',
  417. '0354-11-20 21:25:15',
  418. '1333-02-03 21:44:21',
  419. '1800-03-30',
  420. '1650-05-10',
  421. '1754-06-04',
  422. '0904-04-12',
  423. '0199-07-09',
  424. '0001-01-01',
  425. '1899-12-29',
  426. '1899-12-30',
  427. '1899-12-31',
  428. '1900-01-01',
  429. '1899-12-30 18:00:51',
  430. '1899-12-30 04:00:51',
  431. '1899-12-29 04:00:51',
  432. '1899-12-29 18:00:51',
  433. '1903-04-02 01:04:02',
  434. '1815-09-24 03:47:22',
  435. '2100-01-01 01:01:01'
  436. );
  437. var
  438. i, corrTestValueCount : byte;
  439. begin
  440. CreateTableWithFieldType(ftDateTime,FieldtypeDefinitions[ftDateTime]);
  441. TestFieldDeclaration(ftDateTime,8);
  442. if SQLDbType=mysql40 then corrTestValueCount := testValuesCount-21
  443. else corrTestValueCount := testValuesCount;
  444. for i := 0 to corrTestValueCount-1 do
  445. if SQLDbType=oracle then
  446. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (to_date (''' + testValues[i] + ''',''YYYY-MM-DD HH24:MI:SS''))')
  447. else
  448. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (''' + testValues[i] + ''')');
  449. with TSQLDBConnector(DBConnector).Query do
  450. begin
  451. Open;
  452. for i := 0 to corrTestValueCount-1 do
  453. begin
  454. if length(testValues[i]) < 12 then
  455. AssertEquals(testValues[i],FormatDateTime('yyyy/mm/dd',fields[0].AsDateTime))
  456. else
  457. AssertEquals(testValues[i],FormatDateTime('yyyy/mm/dd hh:mm:ss',fields[0].AsDateTime));
  458. Next;
  459. end;
  460. close;
  461. end;
  462. end;
  463. procedure TTestFieldTypes.TestFloat;
  464. const
  465. testValuesCount = 21;
  466. 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);
  467. var
  468. i : byte;
  469. begin
  470. CreateTableWithFieldType(ftFloat,'FLOAT');
  471. TestFieldDeclaration(ftFloat,sizeof(double));
  472. for i := 0 to testValuesCount-1 do
  473. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FT) values (' + floattostr(testValues[i]) + ')');
  474. with TSQLDBConnector(DBConnector).Query do
  475. begin
  476. Open;
  477. for i := 0 to testValuesCount-1 do
  478. begin
  479. AssertEquals(testValues[i],fields[0].AsFloat);
  480. Next;
  481. end;
  482. close;
  483. end;
  484. end;
  485. procedure TTestFieldTypes.TestNullValues;
  486. begin
  487. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT)');
  488. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  489. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  490. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 (FIELD1) values (1)');
  491. with TSQLDBConnector(DBConnector).Query do
  492. begin
  493. sql.clear;
  494. sql.append('select * from FPDEV2');
  495. open;
  496. AssertEquals(1,FieldByName('FIELD1').AsInteger);
  497. AssertTrue('Null-values test failed',FieldByName('FIELD2').IsNull);
  498. close;
  499. end;
  500. end;
  501. procedure TTestFieldTypes.TestParamQuery;
  502. begin
  503. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT, FIELD3 INT, DECOY VARCHAR(30))');
  504. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  505. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  506. with TSQLDBConnector(DBConnector).Query do
  507. begin
  508. sql.clear;
  509. sql.append('insert into FPDEV2 (field1) values (:field1)');
  510. Params.ParamByName('field1').AsInteger := 1;
  511. ExecSQL;
  512. sql.clear;
  513. sql.append('insert into FPDEV2 (field1,field2,decoy) values (:field1,:field2,''decoytest'')');
  514. Params.ParamByName('field1').AsInteger := 2;
  515. Params.ParamByName('field2').DataType := ftInteger;
  516. Params.ParamByName('field2').Value := Null;
  517. ExecSQL;
  518. sql.clear;
  519. sql.append('insert into FPDEV2 (field1,field2,field3) values (:field1,:field2,:field3)');
  520. Params.ParamByName('field1').AsInteger := 3;
  521. Params.ParamByName('field2').AsInteger := 2;
  522. Params.ParamByName('field3').AsInteger := 3;
  523. ExecSQL;
  524. sql.clear;
  525. sql.append('insert into FPDEV2 (field1,field2,field3,decoy) values (:field1,:field2,:field3,'':decoy ::test $decoy2 $$2'')');
  526. Params.ParamByName('field1').AsInteger := 4;
  527. Params.ParamByName('field2').AsInteger := 2;
  528. Params.ParamByName('field3').AsInteger := 3;
  529. ExecSQL;
  530. sql.clear;
  531. sql.append('insert into FPDEV2 (field1,field2,field3) values (:field1,:field2,:field1)');
  532. Params.ParamByName('field1').AsInteger := 5;
  533. Params.ParamByName('field2').AsInteger := 2;
  534. ExecSQL;
  535. sql.clear;
  536. sql.append('select * from FPDEV2 order by FIELD1');
  537. open;
  538. AssertEquals(1,FieldByName('FIELD1').asinteger);
  539. AssertTrue(FieldByName('FIELD2').IsNull);
  540. AssertTrue(FieldByName('FIELD3').IsNull);
  541. AssertTrue(FieldByName('DECOY').IsNull);
  542. next;
  543. AssertEquals(2,FieldByName('FIELD1').asinteger);
  544. AssertTrue(FieldByName('FIELD2').IsNull);
  545. AssertTrue(FieldByName('FIELD3').IsNull);
  546. AssertEquals('decoytest',FieldByName('DECOY').AsString);
  547. next;
  548. AssertEquals(3,FieldByName('FIELD1').asinteger);
  549. AssertEquals(2,FieldByName('FIELD2').asinteger);
  550. AssertEquals(3,FieldByName('FIELD3').asinteger);
  551. AssertTrue(FieldByName('DECOY').IsNull);
  552. next;
  553. AssertEquals(4,FieldByName('FIELD1').asinteger);
  554. AssertEquals(2,FieldByName('FIELD2').asinteger);
  555. AssertEquals(3,FieldByName('FIELD3').asinteger);
  556. AssertEquals(':decoy ::test $decoy2 $$2',FieldByName('DECOY').AsString);
  557. next;
  558. AssertEquals(5,FieldByName('FIELD1').asinteger);
  559. AssertEquals(2,FieldByName('FIELD2').asinteger);
  560. AssertEquals(5,FieldByName('FIELD3').asinteger);
  561. AssertTrue(FieldByName('DECOY').IsNull);
  562. close;
  563. end;
  564. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  565. end;
  566. procedure TTestFieldTypes.TestIntParamQuery;
  567. begin
  568. TestXXParamQuery(ftInteger,'INT',testIntValuesCount);
  569. end;
  570. procedure TTestFieldTypes.TestFloatParamQuery;
  571. begin
  572. TestXXParamQuery(ftFloat,'FLOAT',testFloatValuesCount);
  573. end;
  574. procedure TTestFieldTypes.TestStringParamQuery;
  575. begin
  576. TestXXParamQuery(ftString,'VARCHAR(10)',testValuesCount);
  577. end;
  578. procedure TTestFieldTypes.TestFixedStringParamQuery;
  579. begin
  580. TestXXParamQuery(ftFixedChar,'CHAR(10)',testValuesCount);
  581. end;
  582. procedure TTestFieldTypes.TestDateParamQuery;
  583. begin
  584. TestXXParamQuery(ftDate,'DATE',testDateValuesCount);
  585. end;
  586. procedure TTestFieldTypes.TestXXParamQuery(ADatatype : TFieldType; ASQLTypeDecl : string; testValuescount : integer; Cross : boolean = false);
  587. var i : integer;
  588. begin
  589. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID INT, FIELD1 '+ASQLTypeDecl+')');
  590. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  591. if SQLDbType=interbase then TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  592. with TSQLDBConnector(DBConnector).Query do
  593. begin
  594. PacketRecords := -1;
  595. sql.clear;
  596. sql.append('insert into FPDEV2 (ID,FIELD1) values (:id,:field1)');
  597. ShortDateFormat := 'yyyy-mm-dd';
  598. for i := 0 to testValuesCount -1 do
  599. begin
  600. Params.ParamByName('id').AsInteger := i;
  601. case ADataType of
  602. ftInteger: Params.ParamByName('field1').asinteger := testIntValues[i];
  603. ftFloat : Params.ParamByName('field1').AsFloat := testFloatValues[i];
  604. ftFixedChar,
  605. ftString : Params.ParamByName('field1').AsString := testStringValues[i];
  606. ftDate : if cross then
  607. Params.ParamByName('field1').AsString:= testDateValues[i]
  608. else
  609. Params.ParamByName('field1').AsDateTime:= StrToDate(testDateValues[i]);
  610. else
  611. AssertTrue('no test for paramtype available',False);
  612. end;
  613. ExecSQL;
  614. end;
  615. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  616. sql.clear;
  617. sql.append('select * from FPDEV2 order by ID');
  618. open;
  619. for i := 0 to testValuesCount -1 do
  620. begin
  621. AssertEquals(i,FieldByName('ID').AsInteger);
  622. case ADataType of
  623. ftInteger: AssertEquals(testIntValues[i],FieldByName('FIELD1').AsInteger);
  624. ftFloat : AssertEquals(testFloatValues[i],FieldByName('FIELD1').AsFloat);
  625. ftFixedChar,
  626. ftString : begin
  627. if FieldByName('FIELD1').isnull then
  628. AssertEquals(testStringValues[i],FieldByName('FIELD1').AsString)
  629. else
  630. AssertEquals(PadRight(testStringValues[i],10),FieldByName('FIELD1').AsString);
  631. end;
  632. ftdate : AssertEquals(testDateValues[i],FormatDateTime('yyyy/mm/dd',FieldByName('FIELD1').AsDateTime));
  633. else
  634. AssertTrue('no test for paramtype available',False);
  635. end;
  636. Next;
  637. end;
  638. close;
  639. end;
  640. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  641. end;
  642. procedure TTestFieldTypes.TestSetBlobAsParam(asWhat: integer);
  643. var
  644. i : byte;
  645. ASQL : TSQLQuery;
  646. begin
  647. CreateTableWithFieldType(ftBlob,FieldtypeDefinitions[ftBlob]);
  648. TestFieldDeclaration(ftBlob,0);
  649. ASQL := DBConnector.GetNDataset(True,1) as tsqlquery;
  650. with ASql do
  651. begin
  652. sql.Text := 'insert into FPDEV2 (FT) values (:BlobParam)';
  653. case asWhat of
  654. 0: Params.ParamByName('blobParam').AsMemo := 'Test deze BLob';
  655. 1: Params.ParamByName('blobParam').AsString := 'Test deze BLob';
  656. 2: Params.ParamByName('blobParam').AsBlob := 'Test deze BLob';
  657. end;
  658. ExecSQL;
  659. end;
  660. with TSQLDBConnector(DBConnector).Query do
  661. begin
  662. Open;
  663. if not eof then
  664. AssertEquals('Test deze BLob',fields[0].AsString);
  665. close;
  666. end;
  667. end;
  668. procedure TTestFieldTypes.TestAggregates;
  669. begin
  670. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FIELD1 INT, FIELD2 INT)');
  671. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  672. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  673. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (1,1)');
  674. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (2,3)');
  675. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (3,4)');
  676. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('insert into FPDEV2 values (4,4)');
  677. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  678. with TSQLDBConnector(DBConnector).Query do
  679. begin
  680. sql.clear;
  681. sql.append('select count(*) from FPDEV2');
  682. open;
  683. AssertEquals(4,Fields[0].AsInteger);
  684. close;
  685. sql.clear;
  686. sql.append('select sum(FIELD1) from FPDEV2');
  687. open;
  688. AssertEquals(10,Fields[0].AsInteger);
  689. close;
  690. sql.clear;
  691. sql.append('select avg(FIELD2) from FPDEV2');
  692. open;
  693. AssertEquals(3,Fields[0].AsInteger);
  694. close;
  695. end;
  696. end;
  697. procedure TTestFieldTypes.CreateTableWithFieldType(ADatatype: TFieldType;
  698. ASQLTypeDecl: string);
  699. begin
  700. TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (FT ' +ASQLTypeDecl+ ')');
  701. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  702. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  703. end;
  704. procedure TTestFieldTypes.TestFieldDeclaration(ADatatype: TFieldType;
  705. ADataSize: integer);
  706. begin
  707. with TSQLDBConnector(DBConnector).Query do
  708. begin
  709. SQL.Clear;
  710. SQL.Add('select * from FPDEV2');
  711. Open;
  712. AssertEquals(1,FieldCount);
  713. AssertTrue(CompareText('FT',fields[0].FieldName)=0);
  714. AssertEquals(ADataSize,fields[0].DataSize);
  715. AssertTrue(ADatatype=fields[0].DataType);
  716. Close;
  717. end;
  718. end;
  719. procedure TTestFieldTypes.SetUp;
  720. begin
  721. InitialiseDBConnector;
  722. end;
  723. procedure TTestFieldTypes.TearDown;
  724. begin
  725. if assigned(DBConnector) then
  726. TSQLDBConnector(DBConnector).Transaction.Rollback;
  727. FreeAndNil(DBConnector);
  728. end;
  729. procedure TTestFieldTypes.RunTest;
  730. begin
  731. // if (SQLDbType in TSQLDBTypes) then
  732. inherited RunTest;
  733. end;
  734. procedure TTestFieldTypes.TestClearUpdateableStatus;
  735. // Test if CanModify is correctly disabled in case of a select query without
  736. // a from-statement.
  737. begin
  738. if not (SQLDbType in MySQLdbTypes) then Ignore('This test does only apply to MySQL because the used SQL-statement is MySQL only.');
  739. with TSQLDBConnector(DBConnector) do
  740. begin
  741. with (GetNDataset(false,5) as TSQLQuery) do
  742. begin
  743. Open;
  744. AssertEquals(True,CanModify);
  745. Close;
  746. SQL.Text:='select last_insert_id();';
  747. Open;
  748. AssertEquals(False,CanModify);
  749. close;
  750. end;
  751. end;
  752. end;
  753. procedure TTestFieldTypes.TestReadOnlyParseSQL;
  754. begin
  755. with TSQLDBConnector(DBConnector) do
  756. begin
  757. GetFieldDataset(True);
  758. with query do
  759. begin
  760. AssertFalse(ReadOnly);
  761. AssertTrue(ParseSQL);
  762. // If ParseSQL is false, and no update-queries are given, the query
  763. // shouldn't be updateable after open.
  764. ParseSQL := False;
  765. AssertFalse(ParseSQL);
  766. AssertFalse(ReadOnly);
  767. SQL.Text := 'select * from FPDEV;';
  768. open;
  769. AssertFalse(ParseSQL);
  770. AssertFalse(ReadOnly);
  771. AssertFalse(CanModify);
  772. close;
  773. // If ParseSQL is true, the query should be updateable after open.
  774. ReadOnly := False;
  775. ParseSQL := True;
  776. AssertTrue(ParseSQL);
  777. AssertFalse(ReadOnly);
  778. SQL.Text := 'select * from FPDEV;';
  779. open;
  780. AssertTrue(ParseSQL);
  781. AssertFalse(ReadOnly);
  782. AssertTrue(CanModify);
  783. edit;
  784. FieldByName('ID').AsInteger:=321;
  785. post;
  786. Applyupdates;
  787. close;
  788. // If ParseSQL is true, but the supplied query isn't updateable, then
  789. // the query shouldn't be updateable after open.
  790. ReadOnly := False;
  791. SQL.Text:='select ID,NAME from FPDEV where ID<5';
  792. sql.Add('union');
  793. sql.Add('select ID,NAME from FPDEV where ID>5');
  794. AssertTrue(ParseSQL);
  795. AssertFalse(ReadOnly);
  796. open;
  797. AssertTrue(ParseSQL);
  798. AssertFalse(ReadOnly);
  799. AssertFalse(CanModify);
  800. close;
  801. // As above, but now with an update-query, so that the query should
  802. // be updateable again.
  803. ReadOnly := False;
  804. AssertTrue(ParseSQL);
  805. AssertFalse(ReadOnly);
  806. UpdateSQL.Text:='update FPDEV set ID=:ID where ID=:OLD_ID';
  807. open;
  808. AssertTrue(ParseSQL);
  809. AssertFalse(ReadOnly);
  810. AssertTrue(CanModify);
  811. edit;
  812. post;
  813. Applyupdates;
  814. close;
  815. // Also if ParseSQL is False, the query should be updateable if a update-
  816. // query is given.
  817. ReadOnly := False;
  818. ParseSQL := False;
  819. AssertFalse(ParseSQL);
  820. AssertFalse(ReadOnly);
  821. open;
  822. AssertFalse(ParseSQL);
  823. AssertFalse(ReadOnly);
  824. AssertTrue(CanModify);
  825. edit;
  826. FieldByName('ID').AsInteger:=1;
  827. post;
  828. Applyupdates;
  829. close;
  830. // But if ReadOnly is true, then CanModify should always be false
  831. ReadOnly := True;
  832. ParseSQL := False;
  833. AssertFalse(ParseSQL);
  834. AssertTrue(ReadOnly);
  835. open;
  836. AssertFalse(ParseSQL);
  837. AssertTrue(ReadOnly);
  838. AssertFalse(CanModify);
  839. close;
  840. end;
  841. end;
  842. end;
  843. procedure TTestFieldTypes.TestParseJoins;
  844. begin
  845. with TSQLDBConnector(DBConnector) do
  846. begin
  847. with query do
  848. begin
  849. SQL.Text:='select TT.NAME from FPDEV left join FPDEV TT on TT.ID=FPDEV.ID';
  850. Open;
  851. close;
  852. end;
  853. end;
  854. end;
  855. procedure TTestFieldTypes.TestDoubleFieldNames;
  856. begin
  857. with TSQLDBConnector(DBConnector) do
  858. begin
  859. with query do
  860. begin
  861. SQL.Text:='select FPDEV.*,TT.* from FPDEV left join FPDEV TT on TT.ID=FPDEV.ID';
  862. Open;
  863. AssertTrue(assigned(FindField('ID')));
  864. AssertTrue (assigned(FindField('ID_1')));
  865. AssertTrue(assigned(FindField('NAME')));
  866. AssertTrue(assigned(FindField('NAME_1')));
  867. AssertEquals(1,fieldbyname('ID').AsInteger);
  868. AssertEquals(1,fieldbyname('ID_1').AsInteger);
  869. AssertEquals('TestName1',fieldbyname('NAME').AsString);
  870. AssertEquals('TestName1',fieldbyname('NAME_1').AsString);
  871. close;
  872. end;
  873. end;
  874. end;
  875. procedure TTestFieldTypes.TestParseUnion;
  876. begin
  877. with TSQLDBConnector(DBConnector) do
  878. begin
  879. with query do
  880. begin
  881. SQL.Text:='select NAME from FPDEV where ID<5';
  882. sql.Add('union');
  883. sql.Add('select NAME from FPDEV where ID>5');
  884. Open;
  885. close;
  886. end;
  887. end;
  888. end;
  889. procedure TTestFieldTypes.TestInsertLargeStrFields;
  890. begin
  891. with TSQLDBConnector(DBConnector) do
  892. begin
  893. Connection.ExecuteDirect('create table FPDEV2 ( ' +
  894. ' ID INT NOT NULL , ' +
  895. ' NAME VARCHAR(16000), ' +
  896. ' PRIMARY KEY (ID) ' +
  897. ') ');
  898. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  899. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  900. Query.SQL.Text := 'insert into FPDEV2(ID,NAME) values (1,''test1'')';
  901. Query.ExecSQL;
  902. query.sql.Text:='select * from FPDEV2';
  903. Query.Open;
  904. AssertEquals(query.FieldByName('NAME').AsString,'test1');
  905. Query.insert;
  906. query.fields[1].AsString:='11';
  907. query.Close;
  908. end;
  909. end;
  910. procedure TTestFieldTypes.TestNumericNames;
  911. begin
  912. with TSQLDBConnector(DBConnector) do
  913. begin
  914. if not (SQLDbType in MySQLdbTypes) then
  915. Connection.ExecuteDirect('create table FPDEV2 ( ' +
  916. ' "2ID" INT NOT NULL , ' +
  917. ' "3TEST" VARCHAR(10), ' +
  918. ' PRIMARY KEY ("2ID") ' +
  919. ') ')
  920. else
  921. Connection.ExecuteDirect('create table FPDEV2 ( ' +
  922. ' 2ID INT NOT NULL , ' +
  923. ' 3TEST VARCHAR(10), ' +
  924. ' PRIMARY KEY (2ID) ' +
  925. ') ');
  926. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  927. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  928. with query do
  929. begin
  930. SQL.Text:='select * from FPDEV2';
  931. Open;
  932. Edit;
  933. fieldbyname('2ID').AsInteger:=1;
  934. fieldbyname('3TEST').AsString:='3test';
  935. Post;
  936. ApplyUpdates(0);
  937. close;
  938. open;
  939. AssertEquals('3test',FieldByName('3TEST').AsString);
  940. Edit;
  941. fieldbyname('3TEST').AsString:='test3';
  942. Post;
  943. ApplyUpdates(0);
  944. open;
  945. AssertEquals('test3',FieldByName('3TEST').AsString);
  946. close;
  947. end;
  948. end;
  949. end;
  950. procedure TTestFieldTypes.TestRowsAffected;
  951. begin
  952. with TSQLDBConnector(DBConnector) do
  953. begin
  954. AssertEquals(-1,query.RowsAffected);
  955. Connection.ExecuteDirect('create table FPDEV2 ( ' +
  956. ' ID INT NOT NULL , ' +
  957. ' NAME VARCHAR(250), ' +
  958. ' PRIMARY KEY (ID) ' +
  959. ') ');
  960. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  961. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  962. Query.SQL.Text := 'insert into FPDEV2(ID,NAME) values (1,''test1'')';
  963. Query.ExecSQL;
  964. AssertEquals(1,query.RowsAffected);
  965. Query.SQL.Text := 'insert into FPDEV2(ID,NAME) values (2,''test2'')';
  966. Query.ExecSQL;
  967. AssertEquals(1,query.RowsAffected);
  968. Query.SQL.Text := 'update FPDEV2 set NAME=''NewTest''';
  969. Query.ExecSQL;
  970. AssertEquals(2,query.RowsAffected);
  971. Query.SQL.Text := 'select * from FPDEV2';
  972. Query.Open;
  973. AssertTrue(query.RowsAffected<>0); // It should return -1 or the number of selected rows.
  974. query.Close;
  975. AssertTrue(query.RowsAffected<>0); // It should return -1 or the same as the last time it was called.
  976. if (SQLDbType = sqlite3) then // sqlite doesn't count the rowsaffected if there is no where-clause
  977. Query.SQL.Text := 'delete from FPDEV2 where 1'
  978. else
  979. Query.SQL.Text := 'delete from FPDEV2';
  980. Query.ExecSQL;
  981. AssertEquals(2,query.RowsAffected);
  982. Query.SQL.Text := 'delete from FPDEV2';
  983. Query.ExecSQL;
  984. AssertEquals(0,query.RowsAffected);
  985. end;
  986. end;
  987. procedure TTestFieldTypes.TestStringsReplace;
  988. begin
  989. AssertEquals('dit is een string',StringsReplace('dit was een string',['was'],['is'],[]));
  990. AssertEquals('dit is een string was een string',StringsReplace('dit was een string was een string',['was'],['is'],[]));
  991. AssertEquals('dit is een string is een string',StringsReplace('dit was een string was een string',['was'],['is'],[rfReplaceAll]));
  992. AssertEquals('dit is een char is een char',StringsReplace('dit was een string was een string',['was','string'],['is','char'],[rfReplaceAll]));
  993. AssertEquals('dit is een string was een string',StringsReplace('dit was een string was een string',['string','was'],['char','is'],[]));
  994. AssertEquals('dit is een char is een strin',StringsReplace('dit was een string was een strin',['string','was'],['char','is'],[rfReplaceAll]));
  995. AssertEquals('dit Was een char is een char',StringsReplace('dit Was een string was een string',['was','string'],['is','char'],[rfReplaceAll]));
  996. AssertEquals('dit wAs een char is een char',StringsReplace('dit wAs een string was een string',['was','string'],['is','char'],[rfReplaceAll]));
  997. AssertEquals('dit is een char is een char',StringsReplace('dit Was een sTring was een string',['was','string'],['is','char'],[rfReplaceAll,rfIgnoreCase]));
  998. AssertEquals('dit is een char is een char',StringsReplace('dit wAs een STRING was een string',['was','string'],['is','char'],[rfReplaceAll,rfIgnoreCase]));
  999. AssertEquals('dit was een si was een sa',StringsReplace('dit was een string was een straat',['straat','string'],['sa','si'],[rfReplaceAll]));
  1000. AssertEquals('dit was een si was een sa',StringsReplace('dit was een string was een straat',['string','straat'],['si','sa'],[rfReplaceAll]));
  1001. AssertEquals('dit was een sing was een saat',StringsReplace('dit was een string was een straat',['str','string'],['s','si'],[rfReplaceAll]));
  1002. AssertEquals('dit was een si was een saat',StringsReplace('dit was een string was een straat',['string','str'],['si','s'],[rfReplaceAll]));
  1003. AssertEquals('dit was een string was een string',StringsReplace('dit was een string was een string',[''],['is'],[rfReplaceAll]));
  1004. AssertEquals('dit een string een string',StringsReplace('dit was een string was een string',['was'],[''],[rfReplaceAll]));
  1005. end;
  1006. procedure TTestFieldTypes.TestCircularParams;
  1007. begin
  1008. with TSQLDBConnector(dbconnector) do
  1009. begin
  1010. Connection.ExecuteDirect('create table FPDEV2 (id1 int, id2 int,vchar varchar(10))');
  1011. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  1012. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  1013. Query.sql.Text := 'insert into FPDEV2 values(:id1,:id2,:vchar)';
  1014. query.params[0].asinteger := 1;
  1015. query.params[1].asinteger := 1;
  1016. query.params[2].asstring := '$1 :id2 $';
  1017. query.ExecSQL;
  1018. query.sql.text := 'select * from FPDEV2';
  1019. query.open;
  1020. AssertEquals(1,query.fields[0].asinteger);
  1021. AssertEquals(1,query.fields[1].asinteger);
  1022. AssertEquals('$1 :id2 $',query.fields[2].AsString);
  1023. query.close;
  1024. end;
  1025. end;
  1026. procedure TTestFieldTypes.Test11Params;
  1027. var i : integer;
  1028. begin
  1029. with TSQLDBConnector(dbconnector) do
  1030. begin
  1031. Connection.ExecuteDirect('create table FPDEV2 (id1 int, id2 int, id3 int, id4 int,id5 int,id6 int,id7 int,id8 int, id9 int, id10 int, id11 int)');
  1032. // Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
  1033. TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
  1034. Query.sql.Text := 'insert into FPDEV2 values(:id1,:id2,:id3,:id4,:id5,:id6,:id7,:id8,:id9,:id10,:id11)';
  1035. for i := 0 to 10 do
  1036. query.params[i].asinteger := 1;
  1037. query.ExecSQL;
  1038. query.sql.text := 'select * from FPDEV2';
  1039. query.open;
  1040. for i := 0 to 10 do
  1041. AssertEquals(1,query.fields[i].asinteger);
  1042. query.close;
  1043. end;
  1044. end;
  1045. procedure TTestFieldTypes.TestBug9744;
  1046. var i : integer;
  1047. begin
  1048. if SQLDbType in [interbase,postgresql] then Ignore('This test does not apply to this db-engine, since it has no double field-type');
  1049. with TSQLDBConnector(DBConnector) do
  1050. begin
  1051. try
  1052. Connection.ExecuteDirect('create table TTTOBJ ( ' +
  1053. ' ID INT NOT NULL, ' +
  1054. ' NAME VARCHAR(250), ' +
  1055. ' PRIMARY KEY (ID) ' +
  1056. ') ');
  1057. Connection.ExecuteDirect('create table TTTXY ( ' +
  1058. ' ID INT NOT NULL, ' +
  1059. ' NP INT NOT NULL, ' +
  1060. ' X DOUBLE, ' +
  1061. ' Y DOUBLE, ' +
  1062. ' PRIMARY KEY (ID,NP) ' +
  1063. ') ');
  1064. for i := 0 to 7 do
  1065. begin
  1066. connection.ExecuteDirect('insert into TTTOBJ(ID,NAME) values ('+inttostr(i)+',''A'+inttostr(i)+''')');
  1067. connection.ExecuteDirect('insert into TTTXY(ID,NP,X,Y) values ('+inttostr(i)+',1,1,1)');
  1068. connection.ExecuteDirect('insert into TTTXY(ID,NP,X,Y) values ('+inttostr(i)+',2,2,2)');
  1069. end;
  1070. 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';
  1071. query.Prepare;
  1072. query.open;
  1073. query.close;
  1074. finally
  1075. Connection.ExecuteDirect('drop table TTTXY');
  1076. Connection.ExecuteDirect('drop table TTTOBJ');
  1077. end
  1078. end;
  1079. end;
  1080. procedure TTestFieldTypes.TestCrossStringDateParam;
  1081. begin
  1082. TestXXParamQuery(ftDate,'DATE',testDateValuesCount,True);
  1083. end;
  1084. procedure TTestFieldTypes.TestGetFieldNames;
  1085. var FieldNames : TStringList;
  1086. begin
  1087. with TSQLDBConnector(DBConnector) do
  1088. begin
  1089. FieldNames := TStringList.Create;
  1090. try
  1091. if SQLDbType in MySQLdbTypes then
  1092. Connection.GetFieldNames('FPDEV',FieldNames)
  1093. else
  1094. Connection.GetFieldNames('fpDEv',FieldNames);
  1095. AssertEquals(2,FieldNames.Count);
  1096. AssertEquals('ID',UpperCase(FieldNames[0]));
  1097. AssertEquals('NAME',UpperCase(FieldNames[1]));
  1098. finally
  1099. FieldNames.Free;
  1100. end;
  1101. end;
  1102. end;
  1103. procedure TTestFieldTypes.TestGetTables;
  1104. var TableNames : TStringList;
  1105. begin
  1106. with TSQLDBConnector(DBConnector) do
  1107. begin
  1108. TableNames := TStringList.Create;
  1109. try
  1110. Connection.GetTableNames(TableNames);
  1111. AssertTrue(TableNames.Count>0);
  1112. AssertTrue(TableNames.IndexOf('FPDEV')>-1);
  1113. AssertTrue(TableNames.IndexOf('FPDEV_FIELD')>-1);
  1114. finally
  1115. TableNames.Free;
  1116. end;
  1117. end;
  1118. end;
  1119. procedure TTestFieldTypes.TestUpdateIndexDefs;
  1120. var ds : TSQLQuery;
  1121. begin
  1122. ds := DBConnector.GetNDataset(1) as TSQLQuery;
  1123. ds.Prepare;
  1124. ds.ServerIndexDefs.Update;
  1125. AssertEquals(1,ds.ServerIndexDefs.count);
  1126. AssertTrue(CompareText('ID',ds.ServerIndexDefs[0].Fields)=0);
  1127. Asserttrue(ds.ServerIndexDefs[0].Options=[ixPrimary,ixUnique]);
  1128. ds.ServerIndexDefs.Update;
  1129. AssertEquals(1,ds.ServerIndexDefs.count);
  1130. AssertTrue(CompareText('ID',ds.ServerIndexDefs[0].Fields)=0);
  1131. Asserttrue(ds.ServerIndexDefs[0].Options=[ixPrimary,ixUnique]);
  1132. end;
  1133. procedure TTestFieldTypes.TestSetBlobAsMemoParam;
  1134. begin
  1135. TestSetBlobAsParam(0);
  1136. end;
  1137. procedure TTestFieldTypes.TestSetBlobAsBlobParam;
  1138. begin
  1139. TestSetBlobAsParam(2);
  1140. end;
  1141. procedure TTestFieldTypes.TestTemporaryTable;
  1142. begin
  1143. if SQLDbType=interbase then Ignore('This test does not apply to Interbase/Firebird, since it doesn''t support temporary tables');
  1144. with TSQLDBConnector(DBConnector).Query do
  1145. begin
  1146. SQL.Clear;
  1147. SQL.Add('CREATE TEMPORARY TABLE TEMP1 (id int)');
  1148. ExecSQL;
  1149. SQL.Text := 'INSERT INTO TEMP1(id) values (5)';
  1150. ExecSQL;
  1151. SQL.Text := 'SELECT * FROM TEMP1';
  1152. Open;
  1153. AssertEquals(5,fields[0].AsInteger);
  1154. Close;
  1155. end;
  1156. end;
  1157. procedure TTestFieldTypes.TestGetIndexDefs;
  1158. var ds : TSQLQuery;
  1159. inddefs : TIndexDefs;
  1160. begin
  1161. ds := DBConnector.GetNDataset(1) as TSQLQuery;
  1162. ds.Open;
  1163. AssertEquals(1,ds.ServerIndexDefs.count);
  1164. inddefs := HackedDataset(ds).GetIndexDefs(ds.ServerIndexDefs,[ixPrimary]);
  1165. AssertEquals(1,inddefs.count);
  1166. AssertTrue(CompareText('ID',inddefs[0].Fields)=0);
  1167. Asserttrue(inddefs[0].Options=[ixPrimary,ixUnique]);
  1168. inddefs.Free;
  1169. inddefs := HackedDataset(ds).GetIndexDefs(ds.ServerIndexDefs,[ixPrimary,ixUnique]);
  1170. AssertEquals(1,inddefs.count);
  1171. AssertTrue(CompareText('ID',inddefs[0].Fields)=0);
  1172. Asserttrue(inddefs[0].Options=[ixPrimary,ixUnique]);
  1173. inddefs.Free;
  1174. inddefs := HackedDataset(ds).GetIndexDefs(ds.ServerIndexDefs,[ixDescending]);
  1175. AssertEquals(0,inddefs.count);
  1176. inddefs.Free;
  1177. end;
  1178. procedure TTestFieldTypes.TestDblQuoteEscComments;
  1179. begin
  1180. with TSQLDBConnector(DBConnector).Query do
  1181. begin
  1182. SQL.Clear;
  1183. SQL.Add('select * from FPDEV where name=''test '''' and :ThisIsNotAParameter ''');
  1184. open;
  1185. close;
  1186. end;
  1187. end;
  1188. procedure TTestFieldTypes.TestParametersAndDates;
  1189. // See bug 7205
  1190. var ADateStr : String;
  1191. begin
  1192. if SQLDbType in [interbase,mysql40,mysql41,mysql50] then Ignore('This test does not apply to this sqldb-connection type, since it doesn''t use semicolons for casts');
  1193. with TSQLDBConnector(DBConnector).Query do
  1194. begin
  1195. SQL.Clear;
  1196. sql.add('select now()::date as current_date where 1=1');
  1197. open;
  1198. first;
  1199. ADateStr:=fields[0].asstring; // return the correct date
  1200. // writeln(fields[0].asstring);
  1201. close;
  1202. sql.clear;
  1203. sql.add('select now()::date as current_date where cast(1 as integer) = :PARAM1');
  1204. params.parambyname('PARAM1').asinteger:= 1;
  1205. open;
  1206. first;
  1207. AssertEquals(ADateStr,fields[0].asstring); // return invalid date
  1208. // writeln(fields[0].asstring);
  1209. close;
  1210. end
  1211. end;
  1212. procedure TTestFieldTypes.TestExceptOnsecClose;
  1213. var passed : boolean;
  1214. begin
  1215. with TSQLDBConnector(DBConnector).Query do
  1216. begin
  1217. SQL.Clear;
  1218. SQL.Add('select * from FPDEV');
  1219. Open;
  1220. close;
  1221. SQL.Clear;
  1222. SQL.Add('select blaise from FPDEV');
  1223. passed := false;
  1224. try
  1225. open;
  1226. except
  1227. on E: Exception do
  1228. passed := (E.ClassType.InheritsFrom(EDatabaseError))
  1229. end;
  1230. AssertTrue(passed);
  1231. Close;
  1232. end;
  1233. end;
  1234. initialization
  1235. if uppercase(dbconnectorname)='SQL' then RegisterTest(TTestFieldTypes);
  1236. end.