mysqldb.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. unit MySQLDB;
  2. {$H+}
  3. interface
  4. uses
  5. SysUtils, Classes, db, mysql,mysql_com;
  6. type
  7. PMySQLDatasetBookmark = ^TMySQLDatasetBookmark;
  8. TMySQLDatasetBookmark = record
  9. BookmarkData: Integer;
  10. BookmarkFlag: TBookmarkFlag;
  11. end;
  12. Pinteger = ^Integer;
  13. TMySQLDataset = class(TDataSet)
  14. private
  15. FSQL: TStrings;
  16. FDatabase: string;
  17. FHost: string;
  18. FPort: Integer;
  19. FUser: string;
  20. FPassword: string;
  21. FRecordSize: Integer;
  22. FBufferSize: Integer;
  23. // MySQL data
  24. FMYSQL: PMYSQL;
  25. FMYSQLRES: PMYSQL_RES;
  26. FCurrentRecord: Integer; { Record pointer }
  27. FServerInfo: string;
  28. FHostInfo: string;
  29. FAffectedRows: QWord;
  30. FLastInsertID: Integer;
  31. FLoadingFieldDefs: Boolean;
  32. procedure DoOpen;
  33. procedure DoClose;
  34. procedure DoQuery;
  35. procedure DoGetResult;
  36. procedure CalculateSizes;
  37. procedure LoadBufferFromData(Buffer: PChar);
  38. function GetServerStatus: string;
  39. protected
  40. procedure SetDatabase(const Value: string);
  41. procedure SetSQL(const Value: TStrings);
  42. function GetClientInfo: string;
  43. function InternalStrToFloat(S: string): Extended;
  44. function InternalStrToDate(S: string): TDateTime;
  45. function InternalStrToTime(S: string): TDateTime;
  46. function InternalStrToDateTime(S: string): TDateTime;
  47. function InternalStrToTimeStamp(S: string): TDateTime;
  48. function MySQLFieldToFieldType(AType: enum_field_types; ASize: Integer;
  49. var NewType: TFieldType; var NewSize: Integer): Boolean;
  50. function MySQLDataSize(AType: enum_field_types; ASize: Integer): Integer;
  51. function MySQLWriteFieldData(AType: enum_field_types; ASize: Integer; Source: PChar;
  52. Dest: PChar): Integer;
  53. function GetCanModify: Boolean; override;
  54. { Mandatory overrides }
  55. // Record buffer methods:
  56. function AllocRecordBuffer: PChar; override;
  57. procedure FreeRecordBuffer(var Buffer: PChar); override;
  58. procedure InternalInitRecord(Buffer: PChar); override;
  59. function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
  60. function GetRecordSize: Word; override;
  61. procedure SetFieldData(Field: TField; Buffer: Pointer); override;
  62. // Bookmark methods:
  63. procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
  64. function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
  65. procedure InternalGotoBookmark(ABookmark: Pointer); override;
  66. procedure InternalSetToRecord(Buffer: PChar); override;
  67. procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
  68. procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
  69. // Navigational methods:
  70. procedure InternalFirst; override;
  71. procedure InternalLast; override;
  72. // Editing methods:
  73. procedure InternalAddRecord(Buffer: Pointer; DoAppend: Boolean); override;
  74. procedure InternalDelete; override;
  75. procedure InternalPost; override;
  76. // Misc methods:
  77. procedure InternalClose; override;
  78. procedure InternalHandleException; override;
  79. procedure InternalInitFieldDefs; override;
  80. procedure InternalOpen; override;
  81. function IsCursorOpen: Boolean; override;
  82. { Optional overrides }
  83. function GetRecordCount: Integer; override;
  84. function GetRecNo: Integer; override;
  85. procedure SetRecNo(Value: Integer); override;
  86. public
  87. constructor Create(AOwner: TComponent); override;
  88. destructor Destroy; override;
  89. procedure ExecSQL;
  90. // TDataset method
  91. function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
  92. property ServerInfo: string read FServerInfo;
  93. property ClientInfo: string read GetClientInfo;
  94. property HostInfo: string read FHostInfo;
  95. property AffectedRows: QWord read FAffectedRows;
  96. property LastInsertID: Integer read FLastInsertID;
  97. property ServerStatus: string read GetServerStatus;
  98. published
  99. property Active;
  100. property SQL: TStrings read FSQL write SetSQL;
  101. property Database: string read FDatabase write SetDatabase;
  102. property Host: string read FHost write FHost;
  103. property Port: Integer read FPort write FPort;
  104. property User: string read FUser write FUser;
  105. property Password: string read FPassword write FPassword;
  106. property BeforeOpen;
  107. property AfterOpen;
  108. property BeforeClose;
  109. property AfterClose;
  110. property BeforeInsert;
  111. property AfterInsert;
  112. property BeforeEdit;
  113. property AfterEdit;
  114. property BeforePost;
  115. property AfterPost;
  116. property BeforeCancel;
  117. property AfterCancel;
  118. property BeforeDelete;
  119. property AfterDelete;
  120. property BeforeScroll;
  121. property AfterScroll;
  122. property OnDeleteError;
  123. property OnEditError;
  124. end;
  125. implementation
  126. { TMySQLDataset }
  127. constructor TMySQLDataset.Create(AOwner: TComponent);
  128. begin
  129. inherited Create(AOwner);
  130. FSQL := TStringList.Create;
  131. FHost := '';
  132. FPort := 0;
  133. FUser := '';
  134. FPassword := '';
  135. FBufferSize := 0;
  136. FRecordSize := 0;
  137. FCurrentRecord := -1;
  138. FLoadingFieldDefs := False;
  139. FAffectedRows := 0;
  140. FLastInsertID := -1;
  141. FMYSQL := nil;
  142. FMYSQLRES := nil;
  143. end;
  144. destructor TMySQLDataset.Destroy;
  145. begin
  146. FSQL.Free;
  147. inherited destroy;
  148. end;
  149. function TMySQLDataset.AllocRecordBuffer: PChar;
  150. begin
  151. Result := AllocMem(FBufferSize);
  152. end;
  153. procedure TMySQLDataset.FreeRecordBuffer(var Buffer: PChar);
  154. begin
  155. FreeMem(Buffer);
  156. end;
  157. procedure TMySQLDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
  158. begin
  159. PInteger(Data)^ := PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData;
  160. end;
  161. function TMySQLDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  162. begin
  163. Result := PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkFlag;
  164. end;
  165. function TMySQLDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  166. var
  167. I, FC: Integer;
  168. fld: TMYSQL_FIELD;
  169. CurBuf: PChar;
  170. begin
  171. Result := False;
  172. CurBuf := ActiveBuffer;
  173. FC := mysql_num_fields(FMYSQLRES);
  174. for I := 0 to FC-1 do
  175. begin
  176. fld := mysql_fetch_field_direct(FMYSQLRES, I);
  177. //if Field.FieldNo = I+1 then
  178. if Field.FieldName = fld.name then
  179. begin
  180. Move(CurBuf^, PChar(Buffer)^, MySQLDataSize(fld.ftype, fld.length));
  181. if Field.DataType in [ftString{, ftWideString}] then
  182. begin
  183. Result := PChar(buffer)^ <> #0;
  184. if Result then
  185. // Terminate string (necessary for enum fields)
  186. PChar(buffer)[fld.length] := #0;
  187. end else
  188. Result := True;
  189. break;
  190. end
  191. else
  192. Inc(CurBuf, MySQLDataSize(fld.ftype, fld.length));
  193. end;
  194. end;
  195. function TMySQLDataset.GetRecNo: Integer;
  196. begin
  197. UpdateCursorPos;
  198. if (FCurrentRecord = -1) and (RecordCount > 0) then
  199. Result := 1
  200. else
  201. Result := FCurrentRecord + 1;
  202. end;
  203. function TMySQLDataset.GetRecord(Buffer: PChar; GetMode: TGetMode;
  204. DoCheck: Boolean): TGetResult;
  205. begin
  206. if RecordCount < 1 then
  207. Result := grEOF
  208. else
  209. begin
  210. Result := grOk;
  211. case GetMode of
  212. gmPrior:
  213. if FCurrentRecord <= 0 then
  214. begin
  215. Result := grBOF;
  216. FCurrentRecord := -1;
  217. end
  218. else
  219. Dec(FCurrentRecord);
  220. gmCurrent:
  221. if (FCurrentRecord < 0) or (FCurrentRecord >= RecordCount) then
  222. Result := grError;
  223. gmNext:
  224. if FCurrentRecord >= RecordCount-1 then
  225. Result := grEOF
  226. else
  227. Inc(FCurrentRecord);
  228. end;
  229. if Result = grOK then
  230. begin
  231. LoadBufferFromData(Buffer);
  232. with PMySQLDatasetBookmark(Buffer + FRecordSize)^ do
  233. begin
  234. BookmarkData := FCurrentRecord;
  235. BookmarkFlag := bfCurrent;
  236. end;
  237. end
  238. else
  239. if (Result = grError) and (DoCheck) then
  240. DatabaseError('No record');
  241. end;
  242. end;
  243. function TMySQLDataset.GetRecordCount: Integer;
  244. begin
  245. Result := mysql_num_rows(FMYSQLRES);
  246. end;
  247. function TMySQLDataset.GetRecordSize: Word;
  248. begin
  249. Result := FRecordSize;
  250. end;
  251. procedure TMySQLDataset.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
  252. begin
  253. end;
  254. procedure TMySQLDataset.InternalClose;
  255. begin
  256. FCurrentRecord := -1;
  257. DoClose;
  258. if DefaultFields then
  259. DestroyFields;
  260. end;
  261. procedure TMySQLDataset.InternalDelete;
  262. begin
  263. end;
  264. procedure TMySQLDataset.InternalFirst;
  265. begin
  266. FCurrentRecord := -1;
  267. end;
  268. procedure TMySQLDataset.InternalGotoBookmark(ABookmark: Pointer);
  269. begin
  270. FCurrentRecord := PInteger(ABookmark)^;
  271. end;
  272. procedure TMySQLDataset.InternalHandleException;
  273. begin
  274. // Application.HandleException(self);
  275. end;
  276. procedure TMySQLDataset.InternalInitFieldDefs;
  277. var
  278. I, FC: Integer;
  279. field: TMYSQL_FIELD;
  280. DFT: TFieldType;
  281. DFS: Integer;
  282. WasClosed: Boolean;
  283. begin
  284. if FLoadingFieldDefs then Exit;
  285. FLoadingFieldDefs := True;
  286. try
  287. WasClosed := not IsCursorOpen;
  288. if WasClosed then
  289. begin
  290. DoOpen;
  291. DoQuery;
  292. DoGetResult;
  293. end;
  294. try
  295. FieldDefs.Clear;
  296. FC := mysql_num_fields(FMYSQLRES);
  297. for I := 0 to FC-1 do
  298. begin
  299. field := mysql_fetch_field_direct(FMYSQLRES, I);
  300. if MySQLFieldToFieldType(field.ftype, field.length, DFT, DFS) then
  301. TFieldDef.Create(FieldDefs, field.name, DFT, DFS, False, I+1);
  302. end;
  303. finally
  304. if WasClosed then
  305. begin
  306. DoClose;
  307. end;
  308. end;
  309. finally
  310. FLoadingFieldDefs := False;
  311. end;
  312. end;
  313. procedure TMySQLDataset.InternalInitRecord(Buffer: PChar);
  314. begin
  315. FillChar(Buffer^, FBufferSize, 0);
  316. end;
  317. procedure TMySQLDataset.InternalLast;
  318. begin
  319. FCurrentRecord := RecordCount;
  320. end;
  321. procedure TMySQLDataset.InternalOpen;
  322. begin
  323. FMYSQL := nil;
  324. FMYSQLRES := nil;
  325. try
  326. DoOpen;
  327. DoQuery;
  328. DoGetResult;
  329. FCurrentRecord := -1;
  330. InternalInitFieldDefs;
  331. if DefaultFields then
  332. CreateFields;
  333. CalculateSizes;
  334. BindFields(True);
  335. except
  336. DoClose;
  337. FMYSQL := nil;
  338. FMYSQLRES := nil;
  339. raise;
  340. end;
  341. FServerInfo := mysql_get_server_info(FMYSQL);
  342. FHostInfo := mysql_get_host_info(FMYSQL);
  343. BookMarkSize:=SizeOf(Longint);
  344. end;
  345. procedure TMySQLDataset.InternalSetToRecord(Buffer: PChar);
  346. begin
  347. FCurrentRecord := PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData;
  348. end;
  349. function TMySQLDataset.IsCursorOpen: Boolean;
  350. begin
  351. Result := FMYSQL <> nil;
  352. end;
  353. procedure TMySQLDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
  354. begin
  355. PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData := PInteger(Data)^;
  356. end;
  357. procedure TMySQLDataset.SetBookmarkFlag(Buffer: PChar;
  358. Value: TBookmarkFlag);
  359. begin
  360. PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkFlag := Value;
  361. end;
  362. procedure TMySQLDataset.SetFieldData(Field: TField; Buffer: Pointer);
  363. begin
  364. end;
  365. procedure TMySQLDataset.SetRecNo(Value: Integer);
  366. begin
  367. if (Value >= 0) and (Value <= RecordCount-1) then
  368. begin
  369. FCurrentRecord := Value-1;
  370. Resync([]);
  371. end;
  372. end;
  373. procedure TMySQLDataset.SetSQL(const Value: TStrings);
  374. begin
  375. FSQL.Assign(Value);
  376. FieldDefs.Clear;
  377. end;
  378. procedure TMySQLDataset.ExecSQL;
  379. begin
  380. try
  381. DoOpen;
  382. try
  383. DoQuery;
  384. finally
  385. DoClose;
  386. end;
  387. finally
  388. FMYSQLRES := nil;
  389. FMYSQL := nil;
  390. end;
  391. end;
  392. procedure TMySQLDataset.SetDatabase(const Value: string);
  393. begin
  394. FDatabase := Value;
  395. end;
  396. procedure TMySQLDataset.InternalPost;
  397. begin
  398. end;
  399. function TMySQLDataset.GetClientInfo: string;
  400. begin
  401. Result := mysql_get_client_info;
  402. end;
  403. function TMySQLDataset.MySQLFieldToFieldType(AType: enum_field_types; ASize: Integer;
  404. var NewType: TFieldType; var NewSize: Integer): Boolean;
  405. begin
  406. Result := True;
  407. case AType of
  408. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  409. FIELD_TYPE_INT24:
  410. begin
  411. NewType := ftInteger;
  412. NewSize := 0;
  413. end;
  414. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  415. begin
  416. NewType := ftFloat;
  417. NewSize := 0;
  418. end;
  419. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  420. begin
  421. NewType := ftDateTime;
  422. NewSize := 0;
  423. end;
  424. FIELD_TYPE_DATE:
  425. begin
  426. NewType := ftDate;
  427. NewSize := 0;
  428. end;
  429. FIELD_TYPE_TIME:
  430. begin
  431. NewType := ftTime;
  432. NewSize := 0;
  433. end;
  434. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  435. begin
  436. NewType := ftString;
  437. NewSize := ASize;
  438. end;
  439. else
  440. Result := False;
  441. end;
  442. end;
  443. procedure TMySQLDataset.CalculateSizes;
  444. var
  445. I, FC: Integer;
  446. field: TMYSQL_FIELD;
  447. begin
  448. FRecordSize := 0;
  449. FC := mysql_num_fields(FMYSQLRES);
  450. for I := 0 to FC-1 do
  451. begin
  452. field := mysql_fetch_field_direct(FMYSQLRES, I);
  453. FRecordSize := FRecordSize + MySQLDataSize(field.ftype, field.length);
  454. end;
  455. FBufferSize := FRecordSize + SizeOf(TMySQLDatasetBookmark);
  456. end;
  457. procedure TMySQLDataset.LoadBufferFromData(Buffer: PChar);
  458. var
  459. I, FC, CT: Integer;
  460. field: TMYSQL_FIELD;
  461. row: TMYSQL_ROW;
  462. begin
  463. mysql_data_seek(FMYSQLRES, FCurrentRecord);
  464. row := mysql_fetch_row(FMYSQLRES);
  465. if row = nil then
  466. DatabaseError(mysql_error(FMYSQL));
  467. FC := mysql_num_fields(FMYSQLRES);
  468. for I := 0 to FC-1 do
  469. begin
  470. field := mysql_fetch_field_direct(FMYSQLRES, I);
  471. CT := MySQLWriteFieldData(field.ftype, field.length, row^, Buffer);
  472. Inc(Buffer, CT);
  473. Inc(row);
  474. end;
  475. end;
  476. function TMySQLDataset.MySQLDataSize(AType: enum_field_types;
  477. ASize: Integer): Integer;
  478. begin
  479. Result := 0;
  480. case AType of
  481. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  482. FIELD_TYPE_INT24:
  483. begin
  484. Result := SizeOf(Integer);
  485. end;
  486. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  487. begin
  488. Result := SizeOf(Double);
  489. end;
  490. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATE, FIELD_TYPE_TIME, FIELD_TYPE_DATETIME:
  491. begin
  492. Result := SizeOf(TDateTime);
  493. end;
  494. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  495. begin
  496. Result := ASize;
  497. end;
  498. end;
  499. end;
  500. function TMySQLDataset.MySQLWriteFieldData(AType: enum_field_types;
  501. ASize: Integer; Source, Dest: PChar): Integer;
  502. var
  503. VI: Integer;
  504. VF: Double;
  505. VD: TDateTime;
  506. begin
  507. Result := 0;
  508. case AType of
  509. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  510. FIELD_TYPE_INT24:
  511. begin
  512. Result := SizeOf(Integer);
  513. if Source <> '' then
  514. VI := StrToInt(Source)
  515. else
  516. VI := 0;
  517. Move(VI, Dest^, Result);
  518. end;
  519. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  520. begin
  521. Result := SizeOf(Double);
  522. if Source <> '' then
  523. VF := InternalStrToFloat(Source)
  524. else
  525. VF := 0;
  526. Move(VF, Dest^, Result);
  527. end;
  528. FIELD_TYPE_TIMESTAMP:
  529. begin
  530. Result := SizeOf(TDateTime);
  531. if Source <> '' then
  532. VD := InternalStrToTimeStamp(Source)
  533. else
  534. VD := 0;
  535. Move(VD, Dest^, Result);
  536. end;
  537. FIELD_TYPE_DATETIME:
  538. begin
  539. Result := SizeOf(TDateTime);
  540. if Source <> '' then
  541. VD := InternalStrToDateTime(Source)
  542. else
  543. VD := 0;
  544. Move(VD, Dest^, Result);
  545. end;
  546. FIELD_TYPE_DATE:
  547. begin
  548. Result := SizeOf(TDateTime);
  549. if Source <> '' then
  550. VD := InternalStrToDate(Source)
  551. else
  552. VD := 0;
  553. Move(VD, Dest^, Result);
  554. end;
  555. FIELD_TYPE_TIME:
  556. begin
  557. Result := SizeOf(TDateTime);
  558. if Source <> '' then
  559. VD := InternalStrToTime(Source)
  560. else
  561. VD := 0;
  562. Move(VD, Dest^, Result);
  563. end;
  564. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  565. begin
  566. Result := ASize;
  567. if Source <> '' then
  568. Move(Source^, Dest^, Result)
  569. else
  570. Dest^ := #0;
  571. end;
  572. end;
  573. end;
  574. function TMySQLDataset.InternalStrToFloat(S: string): Extended;
  575. var
  576. I: Integer;
  577. Tmp: string;
  578. begin
  579. Tmp := '';
  580. for I := 1 to Length(S) do
  581. begin
  582. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  583. Tmp := Tmp + DecimalSeparator
  584. else
  585. Tmp := Tmp + S[I];
  586. end;
  587. Result := StrToFloat(Tmp);
  588. end;
  589. function TMySQLDataset.InternalStrToDate(S: string): TDateTime;
  590. var
  591. EY, EM, ED: Word;
  592. begin
  593. EY := StrToInt(Copy(S, 1, 4));
  594. EM := StrToInt(Copy(S, 6, 2));
  595. ED := StrToInt(Copy(S, 9, 2));
  596. if (EY = 0) or (EM = 0) or (ED = 0) then
  597. Result := 0
  598. else
  599. Result := EncodeDate(EY, EM, ED);
  600. end;
  601. function TMySQLDataset.InternalStrToDateTime(S: string): TDateTime;
  602. var
  603. EY, EM, ED: Word;
  604. EH, EN, ES: Word;
  605. begin
  606. EY := StrToInt(Copy(S, 1, 4));
  607. EM := StrToInt(Copy(S, 6, 2));
  608. ED := StrToInt(Copy(S, 9, 2));
  609. EH := StrToInt(Copy(S, 11, 2));
  610. EN := StrToInt(Copy(S, 14, 2));
  611. ES := StrToInt(Copy(S, 17, 2));
  612. if (EY = 0) or (EM = 0) or (ED = 0) then
  613. Result := 0
  614. else
  615. Result := EncodeDate(EY, EM, ED);
  616. Result := Result + EncodeTime(EH, EN, ES, 0);
  617. end;
  618. function TMySQLDataset.InternalStrToTime(S: string): TDateTime;
  619. var
  620. EH, EM, ES: Word;
  621. begin
  622. EH := StrToInt(Copy(S, 1, 2));
  623. EM := StrToInt(Copy(S, 4, 2));
  624. ES := StrToInt(Copy(S, 7, 2));
  625. Result := EncodeTime(EH, EM, ES, 0);
  626. end;
  627. function TMySQLDataset.InternalStrToTimeStamp(S: string): TDateTime;
  628. var
  629. EY, EM, ED: Word;
  630. EH, EN, ES: Word;
  631. begin
  632. EY := StrToInt(Copy(S, 1, 4));
  633. EM := StrToInt(Copy(S, 5, 2));
  634. ED := StrToInt(Copy(S, 7, 2));
  635. EH := StrToInt(Copy(S, 9, 2));
  636. EN := StrToInt(Copy(S, 11, 2));
  637. ES := StrToInt(Copy(S, 13, 2));
  638. if (EY = 0) or (EM = 0) or (ED = 0) then
  639. Result := 0
  640. else
  641. Result := EncodeDate(EY, EM, ED);
  642. Result := Result + EncodeTime(EH, EN, ES, 0);;
  643. end;
  644. procedure TMySQLDataset.DoClose;
  645. begin
  646. try
  647. if FMYSQLRES <> nil then
  648. mysql_free_result(FMYSQLRES);
  649. if FMYSQL <> nil then
  650. mysql_close(FMYSQL);
  651. finally
  652. FMYSQLRES := nil;
  653. FMYSQL := nil;
  654. end;
  655. end;
  656. procedure TMySQLDataset.DoOpen;
  657. begin
  658. FMYSQL := mysql_connect(nil, PChar(FHost), PChar(FUser), PChar(FPassword));
  659. if FMYSQL = nil then
  660. DatabaseError('Error connecting to MySQL server');
  661. if FDatabase <> '' then
  662. if mysql_select_db(FMYSQL, PChar(FDatabase)) <> 0 then
  663. DatabaseError(mysql_error(FMYSQL));
  664. end;
  665. procedure TMySQLDataset.DoQuery;
  666. var
  667. Query: PChar;
  668. begin
  669. Query := FSQL.GetText;
  670. try
  671. if mysql_query(FMYSQL, Query) <> 0 then
  672. DatabaseError(mysql_error(FMYSQL));
  673. finally
  674. StrDispose(Query);
  675. end;
  676. FAffectedRows := mysql_affected_rows(FMYSQL);
  677. FLastInsertID := mysql_insert_id(FMYSQL);
  678. end;
  679. function TMySQLDataset.GetCanModify: Boolean;
  680. begin
  681. Result := False;
  682. end;
  683. procedure TMySQLDataset.DoGetResult;
  684. begin
  685. FMYSQLRES := mysql_store_result(FMYSQL);
  686. if FMYSQLRES = nil then
  687. DatabaseError(mysql_error(FMYSQL));
  688. FAffectedRows := mysql_affected_rows(FMYSQL);
  689. end;
  690. function TMySQLDataset.GetServerStatus: string;
  691. begin
  692. CheckActive;
  693. Result := mysql_stat(FMYSQL);
  694. end;
  695. end.
  696. {
  697. $Log$
  698. Revision 1.3 2002-11-07 14:27:59 sg
  699. * AffectedRows now is a QWord (to match recent MySQL versions)
  700. * Result strings for enums etc. are now correctly terminated
  701. * Fixed a memory leak in DoQuery: The query string didn't get released
  702. Revision 1.2 2002/09/07 15:15:23 peter
  703. * old logs removed and tabs fixed
  704. }